Example #1
0
def instrument_inline_candidates(graphs, threshold):
    cache = {None: False}
    def candidate(graph):
        try:
            return cache[graph]
        except KeyError:
            res = static_instruction_count(graph) <= threshold
            cache[graph] = res
            return res
    n = 0
    for parentgraph in graphs:
        for block in parentgraph.iterblocks():
            ops = block.operations
            i = len(ops)-1
            while i >= 0:
                op = ops[i]
                i -= 1
                if op.opname == "direct_call":
                    funcobj = get_funcobj(op.args[0].value)
                    graph = getattr(funcobj, 'graph', None)
                    if graph is not None:
                        if getattr(getattr(funcobj, '_callable', None),
                                   '_dont_inline_', False):
                            continue
                    if candidate(graph):
                        tag = Constant('inline', Void)
                        label = Constant(n, Signed)
                        dummy = Variable()
                        dummy.concretetype = Void
                        count = SpaceOperation('instrument_count',
                                               [tag, label], dummy)
                        ops.insert(i+1, count)
                        n += 1
    log.inlining("%d call sites instrumented" % n)
Example #2
0
    def test_immutable_list_out_of_instance(self):
        from pypy.translator.simplify import get_funcobj
        for immutable_fields in (["a", "b"], ["a", "b", "y[*]"]):

            class A(object):
                _immutable_fields_ = immutable_fields

            class B(A):
                pass

            def f(i):
                b = B()
                lst = [i]
                lst[0] += 1
                b.y = lst
                ll_assert(b.y is lst, "copying when reading out the attr?")
                return b.y[0]

            res = self.interpret(f, [10])
            assert res == 11
            t, rtyper, graph = self.gengraph(f, [int])
            block = graph.startblock
            op = block.operations[-1]
            assert op.opname == 'direct_call'
            func = get_funcobj(op.args[0].value)._callable
            assert ('foldable' in func.func_name) == \
                   ("y[*]" in immutable_fields)
Example #3
0
    def test_immutable_list_out_of_instance(self):
        from pypy.translator.simplify import get_funcobj

        for immutable_fields in (["a", "b"], ["a", "b", "y[*]"]):

            class A(object):
                _immutable_fields_ = immutable_fields

            class B(A):
                pass

            def f(i):
                b = B()
                lst = [i]
                lst[0] += 1
                b.y = lst
                ll_assert(b.y is lst, "copying when reading out the attr?")
                return b.y[0]

            res = self.interpret(f, [10])
            assert res == 11
            t, rtyper, graph = self.gengraph(f, [int])
            block = graph.startblock
            op = block.operations[-1]
            assert op.opname == "direct_call"
            func = get_funcobj(op.args[0].value)._callable
            assert ("foldable" in func.func_name) == ("y[*]" in immutable_fields)
Example #4
0
def instrument_inline_candidates(graphs, threshold):
    cache = {None: False}
    def candidate(graph):
        try:
            return cache[graph]
        except KeyError:
            res = static_instruction_count(graph) <= threshold
            cache[graph] = res
            return res
    n = 0
    for parentgraph in graphs:
        for block in parentgraph.iterblocks():
            ops = block.operations
            i = len(ops)-1
            while i >= 0:
                op = ops[i]
                i -= 1
                if op.opname == "direct_call":
                    funcobj = get_funcobj(op.args[0].value)
                    graph = getattr(funcobj, 'graph', None)
                    if graph is not None:
                        if getattr(getattr(funcobj, '_callable', None),
                                   '_dont_inline_', False):
                            continue
                    if candidate(graph):
                        tag = Constant('inline', Void)
                        label = Constant(n, Signed)
                        dummy = Variable()
                        dummy.concretetype = Void
                        count = SpaceOperation('instrument_count',
                                               [tag, label], dummy)
                        ops.insert(i+1, count)
                        n += 1
    log.inlining("%d call sites instrumented" % n)
Example #5
0
    def test_read_really(self):
        class A(object):
            def __init__(self, y):
                self.y = y
            def f(self):
                self.x = 1
                return self.y
        def h(flag):
            obj = A(flag)
            return obj.f()
        
        t, wa = self.translate(h, [int])
        hgraph = graphof(t, h)
        op_call_f = hgraph.startblock.operations[-1]

        # check that we fished the expected ops
        assert op_call_f.opname == "direct_call"
        assert get_funcobj(op_call_f.args[0].value)._name == 'A.f'

        result = wa.analyze(op_call_f)
        assert len(result) == 2
        result = list(result)
        result.sort()
        [(struct1, T1, name1), (struct2, T2, name2)] = result
        assert struct1 == "readstruct"
        assert name1.endswith("y")
        assert struct2 == "struct"
        assert name2.endswith("x")
        assert T1 == T2
Example #6
0
    def test_read_really(self):
        class A(object):
            def __init__(self, y):
                self.y = y
            def f(self):
                self.x = 1
                return self.y
        def h(flag):
            obj = A(flag)
            return obj.f()
        
        t, wa = self.translate(h, [int])
        hgraph = graphof(t, h)
        op_call_f = hgraph.startblock.operations[-1]

        # check that we fished the expected ops
        assert op_call_f.opname == "direct_call"
        assert get_funcobj(op_call_f.args[0].value)._name == 'A.f'

        result = wa.analyze(op_call_f)
        assert len(result) == 2
        result = list(result)
        result.sort()
        [(struct1, T1, name1), (struct2, T2, name2)] = result
        assert struct1 == "readstruct"
        assert name1.endswith("y")
        assert struct2 == "struct"
        assert name2.endswith("x")
        assert T1 == T2
Example #7
0
File: call.py Project: ieure/pypy
 def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
                  extraeffect=None):
     """Return the calldescr that describes all calls done by 'op'.
     This returns a calldescr that we can put in the corresponding
     call operation in the calling jitcode.  It gets an effectinfo
     describing the effect of the call: which field types it may
     change, whether it can force virtualizables, whether it can
     raise, etc.
     """
     NON_VOID_ARGS = [x.concretetype for x in op.args[1:]
                                     if x.concretetype is not lltype.Void]
     RESULT = op.result.concretetype
     # check the number and type of arguments
     FUNC = get_functype(op.args[0].concretetype)
     ARGS = FUNC.ARGS
     assert NON_VOID_ARGS == [T for T in ARGS if T is not lltype.Void]
     assert RESULT == FUNC.RESULT
     # ok
     # get the 'pure' and 'loopinvariant' flags from the function object
     pure = False
     loopinvariant = False
     if op.opname == "direct_call":
         func = getattr(get_funcobj(op.args[0].value), '_callable', None)
         pure = getattr(func, "_pure_function_", False)
         loopinvariant = getattr(func, "_jit_loop_invariant_", False)
         if loopinvariant:
             assert not NON_VOID_ARGS, ("arguments not supported for "
                                        "loop-invariant function!")
     # build the extraeffect
     can_invalidate = self.quasiimmut_analyzer.analyze(op)
     if extraeffect is None:
         if self.virtualizable_analyzer.analyze(op):
             extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         elif loopinvariant:
             extraeffect = EffectInfo.EF_LOOPINVARIANT
         elif pure:
             # XXX check what to do about exceptions (also MemoryError?)
             extraeffect = EffectInfo.EF_PURE
         elif self._canraise(op):
             extraeffect = EffectInfo.EF_CAN_RAISE
         else:
             extraeffect = EffectInfo.EF_CANNOT_RAISE
     #
     effectinfo = effectinfo_from_writeanalyze(
         self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
         oopspecindex, can_invalidate)
     #
     if oopspecindex != EffectInfo.OS_NONE:
         assert effectinfo is not None
     if pure or loopinvariant:
         assert effectinfo is not None
         assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         # XXX this should also say assert not can_invalidate, but
         #     it can't because our analyzer is not good enough for now
         #     (and getexecutioncontext() can't really invalidate)
     #
     return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                 effectinfo)
Example #8
0
 def analyze_external_call(self, op, seen=None):
     funcobj = get_funcobj(op.args[0].value)
     result = self.bottom_result()
     if hasattr(funcobj, '_callbacks'):
         bk = self.translator.annotator.bookkeeper
         for function in funcobj._callbacks.callbacks:
             desc = bk.getdesc(function)
             for graph in desc.getgraphs():
                 result = self.join_two_results(
                     result, self.analyze_direct_call(graph, seen))
     return result
Example #9
0
def maybe_on_top_of_llinterp(rtyper, fnptr):
    # Run a generated graph on top of the llinterp for testing.
    # When translated, this just returns the fnptr.
    funcobj = get_funcobj(fnptr)
    if hasattr(funcobj, 'graph'):
        llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
        def on_top_of_llinterp(*args):
            return llinterp.eval_graph(funcobj.graph, list(args))
    else:
        assert hasattr(funcobj, '_callable')
        def on_top_of_llinterp(*args):
            return funcobj._callable(*args)
    return on_top_of_llinterp
Example #10
0
def maybe_on_top_of_llinterp(rtyper, fnptr):
    # Run a generated graph on top of the llinterp for testing.
    # When translated, this just returns the fnptr.
    funcobj = get_funcobj(fnptr)
    if hasattr(funcobj, 'graph'):
        llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
        def on_top_of_llinterp(*args):
            return llinterp.eval_graph(funcobj.graph, list(args))
    else:
        assert hasattr(funcobj, '_callable')
        def on_top_of_llinterp(*args):
            return funcobj._callable(*args)
    return on_top_of_llinterp
Example #11
0
def decode_builtin_call(op):
    if op.opname == 'oosend':
        SELFTYPE, name, opargs = decompose_oosend(op)
        return get_send_oopspec(SELFTYPE, name), opargs
    elif op.opname == 'direct_call':
        fnobj = get_funcobj(op.args[0].value)
        opargs = op.args[1:]
        return get_call_oopspec_opargs(fnobj, opargs)
    elif op.opname in ('oostring', 'oounicode'):
        return get_oostring_oopspec(op)
    elif op.opname == 'gc_identityhash':
        return get_identityhash_oopspec(op)
    else:
        raise ValueError(op.opname)
Example #12
0
def iter_callsites(graph, calling_what):
    for block in graph.iterblocks():
        for i, op in enumerate(block.operations):
            if op.opname == "direct_call":
                funcobj = get_funcobj(op.args[0].value)
            elif op.opname == "oosend":
                funcobj = get_meth_from_oosend(op)
                if funcobj is None:
                    continue # cannot inline virtual methods
            else:
                continue

            graph = getattr(funcobj, 'graph', None)
            # accept a function or a graph as 'inline_func'
            if (graph is calling_what or
                getattr(funcobj, '_callable', None) is calling_what):
                yield graph, block, i
Example #13
0
File: inline.py Project: njues/Sypy
def iter_callsites(graph, calling_what):
    for block in graph.iterblocks():
        for i, op in enumerate(block.operations):
            if op.opname == "direct_call":
                funcobj = get_funcobj(op.args[0].value)
            elif op.opname == "oosend":
                funcobj = get_meth_from_oosend(op)
                if funcobj is None:
                    continue  # cannot inline virtual methods
            else:
                continue

            graph = getattr(funcobj, 'graph', None)
            # accept a function or a graph as 'inline_func'
            if (calling_what is None or graph is calling_what
                    or getattr(funcobj, '_callable', None) is calling_what):
                yield graph, block, i
Example #14
0
    def direct_call(hs_f1, *args_hs):
        bookkeeper = getbookkeeper()
        fnobj = get_funcobj(hs_f1.const)
        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

        # normal call
        if not hasattr(fnobj, 'graph'):
            raise NotImplementedError("XXX call to externals or primitives")

        return hs_f1._call_single_graph(fnobj.graph, lltype.typeOf(fnobj).RESULT, *args_hs)
Example #15
0
def maybe_on_top_of_llinterp(rtyper, fnptr):
    # Run a generated graph on top of the llinterp for testing.
    # When translated, this just returns the fnptr.
    def process_args(args):
        real_args = []
        ARGS = lltype.typeOf(funcobj).ARGS
        i = 0
        for ARG in ARGS:
            if ARG is lltype.Void:
                real_args.append(None)
            else:
                if ARG is lltype.Float:
                    real_args.append(args[i])
                elif isinstance(ARG, lltype.Primitive):
                    real_args.append(lltype.cast_primitive(ARG, args[i]))
                elif isinstance(ARG, lltype.Ptr):
                    if ARG.TO._gckind == 'gc':
                        real_args.append(lltype.cast_opaque_ptr(ARG, args[i]))
                    else:
                        real_args.append(rffi.cast(ARG, args[i]))
                else:
                    raise Exception("Unexpected arg: %s" % ARG)
                i += 1
        return real_args

    funcobj = get_funcobj(fnptr)
    if hasattr(funcobj, 'graph'):
        # cache the llinterp; otherwise the remember_malloc/remember_free
        # done on the LLInterpreter don't match
        try:
            llinterp = rtyper._on_top_of_llinterp_llinterp
        except AttributeError:
            llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
            rtyper._on_top_of_llinterp_llinterp = llinterp

        def on_top_of_llinterp(*args):
            real_args = process_args(args)
            return llinterp.eval_graph(funcobj.graph, real_args)
    else:
        assert hasattr(funcobj, '_callable')

        def on_top_of_llinterp(*args):
            args = process_args(args)
            return funcobj._callable(*args)

    return on_top_of_llinterp
Example #16
0
    def direct_call(hs_f1, *args_hs):
        bookkeeper = getbookkeeper()
        fnobj = get_funcobj(hs_f1.const)
        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

        # normal call
        if not hasattr(fnobj, 'graph'):
            raise NotImplementedError("XXX call to externals or primitives")

        return hs_f1._call_single_graph(fnobj.graph,
                                        lltype.typeOf(fnobj).RESULT, *args_hs)
Example #17
0
 def guess_call_kind(self, op, is_candidate=None):
     if op.opname == 'direct_call':
         funcptr = op.args[0].value
         if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None:
             return 'recursive'
         funcobj = get_funcobj(funcptr)
         if getattr(funcobj, 'graph', None) is None:
             return 'residual'
         targetgraph = funcobj.graph
         if (hasattr(targetgraph, 'func') and
             hasattr(targetgraph.func, 'oopspec')):
             return 'builtin'
     elif op.opname == 'oosend':
         SELFTYPE, methname, opargs = support.decompose_oosend(op)
         if SELFTYPE.oopspec_name is not None:
             return 'builtin'
     if self.graphs_from(op, is_candidate) is None:
         return 'residual'
     return 'regular'
Example #18
0
def maybe_on_top_of_llinterp(rtyper, fnptr):
    # Run a generated graph on top of the llinterp for testing.
    # When translated, this just returns the fnptr.
    def process_args(args):
        real_args = []
        ARGS = lltype.typeOf(funcobj).ARGS
        i = 0
        for ARG in ARGS:
            if ARG is lltype.Void:
                real_args.append(None)
            else:
                if ARG is lltype.Float:
                    real_args.append(args[i])
                elif isinstance(ARG, lltype.Primitive):
                    real_args.append(lltype.cast_primitive(ARG, args[i]))
                elif isinstance(ARG, lltype.Ptr):
                    if ARG.TO._gckind == 'gc':
                        real_args.append(lltype.cast_opaque_ptr(ARG, args[i]))
                    else:
                        real_args.append(rffi.cast(ARG, args[i]))
                else:
                    raise Exception("Unexpected arg: %s" % ARG)
                i += 1
        return real_args

    funcobj = get_funcobj(fnptr)
    if hasattr(funcobj, 'graph'):
        # cache the llinterp; otherwise the remember_malloc/remember_free
        # done on the LLInterpreter don't match
        try:
            llinterp = rtyper._on_top_of_llinterp_llinterp
        except AttributeError:
            llinterp = LLInterpreter(rtyper)  #, exc_data_ptr=exc_data_ptr)
            rtyper._on_top_of_llinterp_llinterp = llinterp
        def on_top_of_llinterp(*args):
            real_args = process_args(args)
            return llinterp.eval_graph(funcobj.graph, real_args)
    else:
        assert hasattr(funcobj, '_callable')
        def on_top_of_llinterp(*args):
            args = process_args(args)
            return funcobj._callable(*args)
    return on_top_of_llinterp
Example #19
0
File: call.py Project: njues/Sypy
 def guess_call_kind(self, op, is_candidate=None):
     if op.opname == 'direct_call':
         funcptr = op.args[0].value
         if self.jitdriver_sd_from_portal_runner_ptr(funcptr) is not None:
             return 'recursive'
         funcobj = get_funcobj(funcptr)
         if getattr(funcobj, 'graph', None) is None:
             return 'residual'
         targetgraph = funcobj.graph
         if (hasattr(targetgraph, 'func') and
             hasattr(targetgraph.func, 'oopspec')):
             return 'builtin'
     elif op.opname == 'oosend':
         SELFTYPE, methname, opargs = support.decompose_oosend(op)
         if SELFTYPE.oopspec_name is not None:
             return 'builtin'
     if self.graphs_from(op, is_candidate) is None:
         return 'residual'
     return 'regular'
Example #20
0
File: inline.py Project: njues/Sypy
def inlinable_static_callers(graphs):
    ok_to_call = set(graphs)
    result = []
    for parentgraph in graphs:
        for block in parentgraph.iterblocks():
            for op in block.operations:
                if op.opname == "direct_call":
                    funcobj = get_funcobj(op.args[0].value)
                    graph = getattr(funcobj, 'graph', None)
                    if graph is not None and graph in ok_to_call:
                        if getattr(getattr(funcobj, '_callable', None),
                                   '_dont_inline_', False):
                            continue
                        result.append((parentgraph, graph))
                if op.opname == "oosend":
                    meth = get_meth_from_oosend(op)
                    graph = getattr(meth, 'graph', None)
                    if graph is not None and graph in ok_to_call:
                        result.append((parentgraph, graph))
    return result
Example #21
0
def inlinable_static_callers(graphs):
    ok_to_call = set(graphs)
    result = []
    for parentgraph in graphs:
        for block in parentgraph.iterblocks():
            for op in block.operations:
                if op.opname == "direct_call":
                    funcobj = get_funcobj(op.args[0].value)
                    graph = getattr(funcobj, 'graph', None)
                    if graph is not None and graph in ok_to_call:
                        if getattr(getattr(funcobj, '_callable', None),
                                   '_dont_inline_', False):
                            continue
                        result.append((parentgraph, graph))
                if op.opname == "oosend":
                    meth = get_meth_from_oosend(op)
                    graph = getattr(meth, 'graph', None)
                    if graph is not None and graph in ok_to_call:
                        result.append((parentgraph, graph))
    return result
Example #22
0
File: inline.py Project: njues/Sypy
 def search_for_calls(self, block):
     d = {}
     for i, op in enumerate(block.operations):
         if op.opname == "direct_call":
             funcobj = get_funcobj(op.args[0].value)
         elif op.opname == "oosend":
             funcobj = get_meth_from_oosend(op)
             if funcobj is None:
                 continue
         else:
             continue
         graph = getattr(funcobj, 'graph', None)
         # accept a function or a graph as 'inline_func'
         if (graph is self.inline_func or
                 getattr(funcobj, '_callable', None) is self.inline_func):
             d[i] = graph
     if d:
         self.block_to_index[block] = d
     else:
         try:
             del self.block_to_index[block]
         except KeyError:
             pass
Example #23
0
 def search_for_calls(self, block):
     d = {}
     for i, op in enumerate(block.operations):
         if op.opname == "direct_call":
             funcobj = get_funcobj(op.args[0].value)
         elif op.opname == "oosend":
             funcobj = get_meth_from_oosend(op)
             if funcobj is None:
                 continue
         else:
             continue
         graph = getattr(funcobj, 'graph', None)
         # accept a function or a graph as 'inline_func'
         if (graph is self.inline_func or
             getattr(funcobj, '_callable', None) is self.inline_func):
             d[i] = graph
     if d:
         self.block_to_index[block] = d
     else:
         try:
             del self.block_to_index[block]
         except KeyError:
             pass
Example #24
0
File: call.py Project: njues/Sypy
 def graphs_from(self, op, is_candidate=None):
     if is_candidate is None:
         is_candidate = self.is_candidate
     if op.opname == 'direct_call':
         funcobj = get_funcobj(op.args[0].value)
         graph = funcobj.graph
         if is_candidate(graph):
             return [graph]     # common case: look inside this graph
     else:
         assert op.opname in ('indirect_call', 'oosend')
         if op.opname == 'indirect_call':
             graphs = op.args[-1].value
         else:
             v_obj = op.args[1].concretetype
             graphs = v_obj._lookup_graphs(op.args[0].value)
         #
         if graphs is None:
             # special case: handle the indirect call that goes to
             # the 'instantiate' methods.  This check is a bit imprecise
             # but it's not too bad if we mistake a random indirect call
             # for the one to 'instantiate'.
             from pypy.rpython.lltypesystem import rclass
             CALLTYPE = op.args[0].concretetype
             if (op.opname == 'indirect_call' and len(op.args) == 2 and
                 CALLTYPE == rclass.OBJECT_VTABLE.instantiate):
                 graphs = list(self._graphs_of_all_instantiate())
         #
         if graphs is not None:
             result = []
             for graph in graphs:
                 if is_candidate(graph):
                     result.append(graph)
             if result:
                 return result  # common case: look inside these graphs,
                                # and ignore the others if there are any
     # residual call case: we don't need to look into any graph
     return None
Example #25
0
 def graphs_from(self, op, is_candidate=None):
     if is_candidate is None:
         is_candidate = self.is_candidate
     if op.opname == 'direct_call':
         funcobj = get_funcobj(op.args[0].value)
         graph = funcobj.graph
         if is_candidate(graph):
             return [graph]     # common case: look inside this graph
     else:
         assert op.opname in ('indirect_call', 'oosend')
         if op.opname == 'indirect_call':
             graphs = op.args[-1].value
         else:
             v_obj = op.args[1].concretetype
             graphs = v_obj._lookup_graphs(op.args[0].value)
         #
         if graphs is None:
             # special case: handle the indirect call that goes to
             # the 'instantiate' methods.  This check is a bit imprecise
             # but it's not too bad if we mistake a random indirect call
             # for the one to 'instantiate'.
             from pypy.rpython.lltypesystem import rclass
             CALLTYPE = op.args[0].concretetype
             if (op.opname == 'indirect_call' and len(op.args) == 2 and
                 CALLTYPE == rclass.OBJECT_VTABLE.instantiate):
                 graphs = list(self._graphs_of_all_instantiate())
         #
         if graphs is not None:
             result = []
             for graph in graphs:
                 if is_candidate(graph):
                     result.append(graph)
             if result:
                 return result  # common case: look inside these graphs,
                                # and ignore the others if there are any
     # residual call case: we don't need to look into any graph
     return None
Example #26
0
 def check_call(op, fname):
     assert op.opname == "direct_call"
     assert get_funcobj(op.args[0].value)._name == fname
Example #27
0
File: call.py Project: njues/Sypy
 def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
                  extraeffect=None):
     """Return the calldescr that describes all calls done by 'op'.
     This returns a calldescr that we can put in the corresponding
     call operation in the calling jitcode.  It gets an effectinfo
     describing the effect of the call: which field types it may
     change, whether it can force virtualizables, whether it can
     raise, etc.
     """
     NON_VOID_ARGS = [x.concretetype for x in op.args[1:]
                                     if x.concretetype is not lltype.Void]
     RESULT = op.result.concretetype
     # check the number and type of arguments
     FUNC = get_functype(op.args[0].concretetype)
     ARGS = FUNC.ARGS
     assert NON_VOID_ARGS == [T for T in ARGS if T is not lltype.Void]
     assert RESULT == FUNC.RESULT
     # ok
     # get the 'elidable' and 'loopinvariant' flags from the function object
     elidable = False
     loopinvariant = False
     if op.opname == "direct_call":
         funcobj = get_funcobj(op.args[0].value)
         assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
             "%r: getcalldescr() with a non-default call ABI" % (op,))
         func = getattr(funcobj, '_callable', None)
         elidable = getattr(func, "_elidable_function_", False)
         loopinvariant = getattr(func, "_jit_loop_invariant_", False)
         if loopinvariant:
             assert not NON_VOID_ARGS, ("arguments not supported for "
                                        "loop-invariant function!")
     # build the extraeffect
     random_effects = self.randomeffects_analyzer.analyze(op)
     if random_effects:
         extraeffect = EffectInfo.EF_RANDOM_EFFECTS
     # random_effects implies can_invalidate
     can_invalidate = random_effects or self.quasiimmut_analyzer.analyze(op)
     if extraeffect is None:
         if self.virtualizable_analyzer.analyze(op):
             extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         elif loopinvariant:
             extraeffect = EffectInfo.EF_LOOPINVARIANT
         elif elidable:
             if self._canraise(op):
                 extraeffect = EffectInfo.EF_ELIDABLE_CAN_RAISE
             else:
                 extraeffect = EffectInfo.EF_ELIDABLE_CANNOT_RAISE
         elif self._canraise(op):
             extraeffect = EffectInfo.EF_CAN_RAISE
         else:
             extraeffect = EffectInfo.EF_CANNOT_RAISE
     #
     effectinfo = effectinfo_from_writeanalyze(
         self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
         oopspecindex, can_invalidate)
     #
     assert effectinfo is not None
     if elidable or loopinvariant:
         assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
         # XXX this should also say assert not can_invalidate, but
         #     it can't because our analyzer is not good enough for now
         #     (and getexecutioncontext() can't really invalidate)
     #
     return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
                                 effectinfo)
Example #28
0
 def analyze_external_call(self, op, seen=None):
     fnobj = get_funcobj(op.args[0].value)
     return getattr(fnobj, 'canraise', True)
Example #29
0
 def analyze_external_call(self, op, seen=None):
     fnobj = get_funcobj(op.args[0].value)
     return getattr(fnobj, 'canraise', True)
Example #30
0
 def get_graph_from_op(self, op):
     assert op.opname in ('direct_call', 'oosend')
     if op.opname == 'direct_call':
         return get_funcobj(self.op.args[0].value).graph
     else:
         return get_meth_from_oosend(op).graph
Example #31
0
File: inline.py Project: njues/Sypy
 def get_graph_from_op(self, op):
     assert op.opname in ('direct_call', 'oosend')
     if op.opname == 'direct_call':
         return get_funcobj(self.op.args[0].value).graph
     else:
         return get_meth_from_oosend(op).graph
Example #32
0
 def consider_op_ts_metacall(self, hs_f1, hs_metadesccls, *args_hs):
     bookkeeper = self.bookkeeper
     fnobj = get_funcobj(hs_f1.const)
     return hintmodel.cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
                                         lltype.typeOf(fnobj).RESULT)
Example #33
0
 def consider_op_ts_metacall(self, hs_f1, hs_metadesccls, *args_hs):
     bookkeeper = self.bookkeeper
     fnobj = get_funcobj(hs_f1.const)
     return hintmodel.cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
                                         lltype.typeOf(fnobj).RESULT)