예제 #1
0
    def __init__(self, graph, code):
        self.graph = graph
        func = graph.func
        self.pycode = code
        self.w_globals = Constant(func.func_globals)
        self.blockstack = []

        self.init_closure(func.func_closure)
        self.f_lineno = code.co_firstlineno
        self.last_offset = 0

        self.init_locals_stack(code)

        self.joinpoints = {}
예제 #2
0
def test_format_assembler_loop():
    ssarepr = SSARepr("test")
    i0, i1 = Register('int', 0), Register('int', 1)
    ssarepr.insns = [
        (Label('L1'), ),
        ('goto_if_not_int_gt', i0, Constant(0, lltype.Signed), TLabel('L2')),
        ('int_add', i1, i0, '->', i1),
        ('int_sub', i0, Constant(1, lltype.Signed), '->', i0),
        ('goto', TLabel('L1')),
        (Label('L2'), ),
        ('int_return', i1),
    ]
    asm = format_assembler(ssarepr)
    expected = """
        L1:
        goto_if_not_int_gt %i0, $0, L2
        int_add %i1, %i0 -> %i1
        int_sub %i0, $1 -> %i0
        goto L1
        L2:
        int_return %i1
    """
    assert asm == str(py.code.Source(expected)).strip() + '\n'
예제 #3
0
def test_assemble_list_semibug():
    # the semibug is that after forcing 42 into the dict of constants,
    # it would be reused for all future 42's, even ones that can be
    # encoded directly.
    ssarepr = SSARepr("test")
    ssarepr.insns = [
        ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])),
        ('foobar', ListOfKind('int', [Constant(42, lltype.Signed)])),
        ('baz', Constant(42, lltype.Signed)),
        ('bok', Constant(41, lltype.Signed)),
    ]
    assembler = Assembler()
    jitcode = assembler.assemble(ssarepr)
    assert jitcode.code == ("\x00\x01\xFF"
                            "\x00\x01\xFF"
                            "\x01\x2A"
                            "\x02\xFE")
    assert assembler.insns == {
        'foobar/I': 0,
        'baz/c': 1,  # in USE_C_FORM
        'bok/i': 2
    }  # not in USE_C_FORM
    assert jitcode.constants_i == [42, 41]
예제 #4
0
def test_liveness():
    ssarepr = SSARepr("test")
    i0, i1, i2 = Register('int', 0), Register('int', 1), Register('int', 2)
    ssarepr.insns = [
        ('int_add', i0, Constant(10, lltype.Signed), '->', i1),
        ('-live-', i0, i1, i2),
        ('int_add', i0, Constant(3, lltype.Signed), '->', i2),
        ('-live-', i2),
    ]
    assembler = Assembler()
    jitcode = assembler.assemble(ssarepr)
    assert jitcode.code == (
        "\x00\x00\x0A\x01"  # ends at 4
        "\x01\x00\x00"
        "\x00\x00\x03\x02"  # ends at 13
        "\x01\x04\x00")
    assert assembler.insns == {'int_add/ic>i': 0, 'live/': 1}
    all_liveness = "".join(assembler.all_liveness)
    op_live = assembler.insns['live/']
    with pytest.raises(MissingLiveness):
        jitcode._live_vars(0, all_liveness, op_live)
    assert jitcode._live_vars(4, all_liveness, op_live) == '%i0 %i1 %i2'
    assert jitcode._live_vars(11, all_liveness, op_live) == '%i2'
예제 #5
0
def cutoff_alwaysraising_block(self, block):
    "Fix a block whose end can never be reached at run-time."
    # search the operation that cannot succeed
    can_succeed = [
        op for op in block.operations if op.result.annotation is not None
    ]
    cannot_succeed = [
        op for op in block.operations if op.result.annotation is None
    ]
    n = len(can_succeed)
    # check consistency
    assert can_succeed == block.operations[:n]
    assert cannot_succeed == block.operations[n:]
    assert 0 <= n < len(block.operations)
    # chop off the unreachable end of the block
    del block.operations[n + 1:]
    self.setbinding(block.operations[n].result, annmodel.s_ImpossibleValue)
    # insert the equivalent of 'raise AssertionError'
    graph = self.annotated[block]
    msg = "Call to %r should have raised an exception" % (getattr(
        graph, 'func', None), )
    c1 = Constant(AssertionError)
    c2 = Constant(AssertionError(msg))
    errlink = Link([c1, c2], graph.exceptblock)
    block.recloseblock(errlink, *block.exits)
    # record new link to make the transformation idempotent
    self.links_followed[errlink] = True
    # fix the annotation of the exceptblock.inputargs
    etype, evalue = graph.exceptblock.inputargs
    s_type = annmodel.SomeType()
    s_type.is_type_of = [evalue]
    s_value = annmodel.SomeInstance(
        self.bookkeeper.getuniqueclassdef(Exception))
    self.setbinding(etype, s_type)
    self.setbinding(evalue, s_value)
    # make sure the bookkeeper knows about AssertionError
    self.bookkeeper.getuniqueclassdef(AssertionError)
예제 #6
0
def test_is_pure():
    from rpython.flowspace.model import Variable, Constant
    assert llop.bool_not.is_pure([Variable()])
    assert llop.debug_assert.is_pure([Variable()])
    assert not llop.int_add_ovf.is_pure([Variable(), Variable()])
    #
    S1 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
    v_s1 = Variable()
    v_s1.concretetype = lltype.Ptr(S1)
    assert not llop.setfield.is_pure([v_s1, Constant('x'), Variable()])
    assert not llop.getfield.is_pure([v_s1, Constant('y')])
    #
    A1 = lltype.GcArray(lltype.Signed)
    v_a1 = Variable()
    v_a1.concretetype = lltype.Ptr(A1)
    assert not llop.setarrayitem.is_pure([v_a1, Variable(), Variable()])
    assert not llop.getarrayitem.is_pure([v_a1, Variable()])
    assert llop.getarraysize.is_pure([v_a1])
    #
    S2 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
                         hints={'immutable': True})
    v_s2 = Variable()
    v_s2.concretetype = lltype.Ptr(S2)
    assert not llop.setfield.is_pure([v_s2, Constant('x'), Variable()])
    assert llop.getfield.is_pure([v_s2, Constant('y')])
    #
    A2 = lltype.GcArray(lltype.Signed, hints={'immutable': True})
    v_a2 = Variable()
    v_a2.concretetype = lltype.Ptr(A2)
    assert not llop.setarrayitem.is_pure([v_a2, Variable(), Variable()])
    assert llop.getarrayitem.is_pure([v_a2, Variable()])
    assert llop.getarraysize.is_pure([v_a2])
    #
    for kind in [
            rclass.IR_MUTABLE, rclass.IR_IMMUTABLE, rclass.IR_IMMUTABLE_ARRAY,
            rclass.IR_QUASIIMMUTABLE, rclass.IR_QUASIIMMUTABLE_ARRAY
    ]:
        accessor = rclass.FieldListAccessor()
        S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
                             hints={'immutable_fields': accessor})
        accessor.initialize(S3, {'x': kind})
        v_s3 = Variable()
        v_s3.concretetype = lltype.Ptr(S3)
        assert not llop.setfield.is_pure([v_s3, Constant('x'), Variable()])
        assert not llop.setfield.is_pure([v_s3, Constant('y'), Variable()])
        assert llop.getfield.is_pure([v_s3, Constant('x')]) is kind
        assert not llop.getfield.is_pure([v_s3, Constant('y')])
예제 #7
0
 def emit_const(self, const, kind, allow_short=False):
     value = const.value
     if kind == 'int':
         TYPE = const.concretetype
         if isinstance(TYPE, lltype.Ptr):
             assert TYPE.TO._gckind == 'raw'
             self.see_raw_object(value)
             value = llmemory.cast_ptr_to_adr(value)
             TYPE = llmemory.Address
         if TYPE == llmemory.Address:
             value = heaptracker.adr2int(value)
         if TYPE is lltype.SingleFloat:
             value = longlong.singlefloat2int(value)
         if not isinstance(value,
                           (llmemory.AddressAsInt, ComputedIntSymbolic)):
             value = lltype.cast_primitive(lltype.Signed, value)
             if allow_short:
                 try:
                     short_num = -128 <= value <= 127
                 except TypeError:  # "Symbolics cannot be compared!"
                     short_num = False
                 if short_num:
                     # emit the constant as a small integer
                     self.code.append(chr(value & 0xFF))
                     return True
         constants = self.constants_i
     elif kind == 'ref':
         value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
         constants = self.constants_r
     elif kind == 'float':
         if const.concretetype == lltype.Float:
             value = longlong.getfloatstorage(value)
         else:
             assert longlong.is_longlong(const.concretetype)
             value = rffi.cast(lltype.SignedLongLong, value)
         constants = self.constants_f
     else:
         raise AssemblerError('unimplemented %r in %r' %
                              (const, self.ssareprname))
     key = (kind, Constant(value))
     if key not in self.constants_dict:
         constants.append(value)
         val = 256 - len(constants)
         assert val >= 0, "too many constants"
         self.constants_dict[key] = val
     # emit the constant normally, as one byte that is an index in the
     # list of constants
     self.code.append(chr(self.constants_dict[key]))
     return False
예제 #8
0
파일: support.py 프로젝트: sczfaker/pypy
def builtin_func_for_spec(rtyper,
                          oopspec_name,
                          ll_args,
                          ll_res,
                          extra=None,
                          extrakey=None):
    assert (extra is None) == (extrakey is None)
    key = (oopspec_name, tuple(ll_args), ll_res, extrakey)
    try:
        return rtyper._builtin_func_for_spec_cache[key]
    except (KeyError, AttributeError):
        pass
    args_s = [lltype_to_annotation(v) for v in ll_args]
    if '.' not in oopspec_name:  # 'newxxx' operations
        LIST_OR_DICT = ll_res
    else:
        LIST_OR_DICT = ll_args[0]
    s_result = lltype_to_annotation(ll_res)
    impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra)
    if getattr(impl, 'need_result_type', False):
        if hasattr(rtyper, 'annotator'):
            bk = rtyper.annotator.bookkeeper
            ll_restype = ll_res
            if impl.need_result_type != 'exact':
                ll_restype = ll_restype.TO
            desc = bk.getdesc(ll_restype)
        else:

            class TestingDesc(object):
                knowntype = int
                pyobj = None

            desc = TestingDesc()
        args_s.insert(0, annmodel.SomePBC([desc]))
    #
    if hasattr(rtyper, 'annotator'):  # regular case
        mixlevelann = MixLevelHelperAnnotator(rtyper)
        c_func = mixlevelann.constfunc(impl, args_s, s_result)
        mixlevelann.finish()
    else:
        # for testing only
        c_func = Constant(oopspec_name,
                          lltype.Ptr(lltype.FuncType(ll_args, ll_res)))
    #
    if not hasattr(rtyper, '_builtin_func_for_spec_cache'):
        rtyper._builtin_func_for_spec_cache = {}
    rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT)
    #
    return c_func, LIST_OR_DICT
예제 #9
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 = op.args[0].value._obj
                    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)
예제 #10
0
 def replace_force_quasiimmut_with_direct_call(self, op):
     ARG = op.args[0].concretetype
     mutatefieldname = op.args[1].value
     key = (ARG, mutatefieldname)
     if key in self._cache_force_quasiimmed_funcs:
         cptr = self._cache_force_quasiimmed_funcs[key]
     else:
         from rpython.jit.metainterp import quasiimmut
         func = quasiimmut.make_invalidation_function(ARG, mutatefieldname)
         FUNC = lltype.Ptr(lltype.FuncType([ARG], lltype.Void))
         llptr = self.helper_func(FUNC, func)
         cptr = Constant(llptr, FUNC)
         self._cache_force_quasiimmed_funcs[key] = cptr
     op.opname = 'direct_call'
     op.args = [cptr, op.args[0]]
예제 #11
0
    def convert_const(self, value):
        if value is None:
            return self.null_wref

        assert isinstance(value, weakref.ReferenceType)
        instance = value()
        bk = self.rtyper.annotator.bookkeeper
        # obscure!  if the annotator hasn't seen this object before,
        # we don't want to look at it now (confusion tends to result).
        if instance is None or not bk.have_seen(instance):
            return self.dead_wref
        else:
            repr = self.rtyper.bindingrepr(Constant(instance))
            llinstance = repr.convert_const(instance)
            return self._weakref_create(llinstance)
예제 #12
0
def test_assemble_cast_consts():
    ssarepr = SSARepr("test")
    S = lltype.GcStruct('S')
    s = lltype.malloc(S)
    F = lltype.FuncType([], lltype.Signed)
    f = lltype.functionptr(F, 'f')
    ssarepr.insns = [
        ('int_return', Constant('X', lltype.Char)),
        ('int_return', Constant(unichr(0x1234), lltype.UniChar)),
        ('int_return', Constant(f, lltype.Ptr(F))),
        ('ref_return', Constant(s, lltype.Ptr(S))),
    ]
    assembler = Assembler()
    jitcode = assembler.assemble(ssarepr)
    assert jitcode.code == ("\x00\x58" "\x01\xFF" "\x01\xFE" "\x02\xFF")
    assert assembler.insns == {
        'int_return/c': 0,
        'int_return/i': 1,
        'ref_return/r': 2
    }
    f_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(f))
    assert jitcode.constants_i == [0x1234, f_int]
    s_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
    assert jitcode.constants_r == [s_gcref]
예제 #13
0
 def test__flowspace_rewrite_directly_as_(self):
     def g(x):
         pass
     def f(x):
         pass
     f._flowspace_rewrite_directly_as_ = g
     def h(x):
         f(x)
     graph = self.codetest(h)
     assert self.all_operations(graph) == {'simple_call': 1}
     for block in graph.iterblocks():
         if block.operations:
             op = block.operations[0]
             assert op.opname == 'simple_call'
             assert op.args[0] == Constant(g)
예제 #14
0
 def consider_lookup_in_type_where(self, bookkeeper, attr):
     assert attr not in self.lookups_where
     from pypy.objspace.std import typeobject
     cached = "cached_where_%s" % attr
     clsdef = bookkeeper.getuniqueclassdef(typeobject.W_TypeObject)
     classdesc = clsdef.classdesc
     classdesc.immutable_fields.add(cached)
     classdesc.classdict[cached] = Constant((None, None))
     clsdef.add_source_for_attribute(cached, classdesc)
     for t in self.pypytypes:
         if not (t.is_heaptype() or t.is_cpytype()):
             setattr(t, cached, t._lookup_where(attr))
             source = InstanceSource(bookkeeper, t)
             clsdef.add_source_for_attribute(cached, source)
     self.lookups_where[attr] = True
예제 #15
0
def recursively_flatten(lst):
    from rpython.flowspace.flowcontext import FlowSignal
    i = 0
    while i < len(lst):
        unroller = lst[i]
        if not isinstance(unroller, FlowSignal):
            i += 1
        else:
            vars = unroller.state_unpack_variables()
            key = unroller.__class__, len(vars)
            try:
                tag = PICKLE_TAGS[key]
            except KeyError:
                tag = PICKLE_TAGS[key] = Constant(PickleTag())
                UNPICKLE_TAGS[tag] = key
            lst[i:i + 1] = [tag] + vars
예제 #16
0
 def test_arg_sublist_1(self):
     v1 = varoftype(lltype.Signed)
     v2 = varoftype(lltype.Char)
     v3 = varoftype(rclass.OBJECTPTR)
     v4 = varoftype(lltype.Ptr(rstr.STR))
     v5 = varoftype(lltype.Float)
     op = SpaceOperation('residual_call_ir_f',
                         [Constant(12345, lltype.Signed),  # function ptr
                          ListOfKind('int', [v1, v2]),     # int args
                          ListOfKind('ref', [v3, v4])],    # ref args
                         v5)                    # result
     flattener = GraphFlattener(None, fake_regallocs())
     flattener.serialize_op(op)
     assert_format(flattener.ssarepr, """
         residual_call_ir_f $12345, I[%i0, %i1], R[%r0, %r1] -> %f0
     """)
예제 #17
0
 def handle_op_malloc(self, op):
     if op.result is self.v_expand_malloc:
         MALLOCTYPE = op.result.concretetype.TO
         typedesc = self.graphbuilder.mallocv.getmalloctypedesc(MALLOCTYPE)
         virtualnode = VirtualSpecNode(typedesc, [])
         self.setnode(op.result, virtualnode)
         for name, FIELDTYPE in typedesc.names_and_types:
             fieldnode = RuntimeSpecNode(name, FIELDTYPE)
             virtualnode.fields.append(fieldnode)
             c = Constant(FIELDTYPE._defl())
             c.concretetype = FIELDTYPE
             self.renamings[fieldnode] = c
         self.v_expand_malloc = None  # done
         return []
     else:
         return self.handle_default(op)
예제 #18
0
 def clone_inlined_jit_merge_points(self, graphs):
     """
     Find all the jit_merge_points in the given graphs, and replace the
     original JitDriver with a fresh clone.
     """
     if not graphs:
         return
     for graph, block, pos in find_jit_merge_points(graphs):
         op = block.operations[pos]
         v_driver = op.args[1]
         driver = v_driver.value
         if not driver.inline_jit_merge_point:
             continue
         new_driver = driver.clone()
         c_new_driver = Constant(new_driver, v_driver.concretetype)
         op.args[1] = c_new_driver
예제 #19
0
def materialize_object(obj_key, state, ops):
    """ Accepts a VirtualState object and creates the required operations, for
    its materialization/initialization. XXX: Edits ops in-place
    """

    if obj_key not in state:
        return False

    # We're gonna delete the object from the state dict first (since it has
    # escaped) for correct recursion reasons in case of cyclic dependency.
    # this needs to be done with all the aliases of the object!
    vo = state[obj_key] # Thus, we'll make a copy first.
    assert obj_key in vo.aliases
    for key in vo.aliases:
        del state[key]

    # Starting assembling the operations. Creation and required castings:
    newvar = Variable()
    newvar.concretetype = vo.concretetype
    ops.append(SpaceOperation('malloc', vo.malloc_args, newvar))

    # recreate the aliases
    for var in vo.aliases:
        if var.concretetype != vo.concretetype:
            ops.append(SpaceOperation('cast_pointer', [newvar], var))
        else:
            ops.append(SpaceOperation('same_as', [newvar], var))

    # Initialization
    for (key, concretetype), value in vo.vars.items():
        if concretetype != vo.concretetype:
            # we need a cast_pointer
            v = Variable()
            v.concretetype = concretetype
            op = SpaceOperation('cast_pointer', [newvar], v)
            ops.append(op)
            target = v
        else:
            target = newvar
        # What if the assigned is a virtual object? Recursion:
        materialize_object(value, state, ops)
        m = Variable()
        m.concretetype = lltype.Void
        ops.append(SpaceOperation('setfield', [target,
                                               Constant(key, lltype.Void),
                                               value], m))
    return True
예제 #20
0
def expand_one_push_roots(regalloc, args):
    if regalloc is None:
        assert len(args) == 0
    else:
        filled = [False] * regalloc.numcolors
        for v in args:
            index = regalloc.getcolor(v)
            assert not filled[index]
            filled[index] = True
            yield _gc_save_root(index, v)
        bitmask_index, bitmask = make_bitmask(filled, regalloc.graph)
        if bitmask_index is not None:
            # xxx we might in some cases avoid this gc_save_root
            # entirely, if we know we're after another gc_push/gc_pop
            # that wrote exactly the same mask at the same index
            bitmask_c = Constant(bitmask, lltype.Signed)
            yield _gc_save_root(bitmask_index, bitmask_c)
예제 #21
0
def constant_diffuse(graph):
    count = 0
    # after 'exitswitch vexit', replace 'vexit' with the corresponding constant
    # if it also appears on the outgoing links
    for block in graph.iterblocks():
        vexit = block.exitswitch
        if isinstance(vexit, Variable):
            for link in block.exits:
                if vexit in link.args and link.exitcase != 'default':
                    remap = {
                        vexit: Constant(link.llexitcase, vexit.concretetype)
                    }
                    link.args = [remap.get(v, v) for v in link.args]
                    count += 1
    # if the same constants appear at the same positions in all links
    # into a block remove them from the links, remove the corresponding
    # input variables and introduce equivalent same_as at the beginning
    # of the block then try to fold the block further
    for block, links in mkentrymap(graph).iteritems():
        if block is graph.startblock:
            continue
        if block.exits == ():
            continue
        firstlink = links[0]
        rest = links[1:]
        diffuse = []
        for i, c in enumerate(firstlink.args):
            if not isinstance(c, Constant):
                continue
            for lnk in rest:
                if lnk.args[i] != c:
                    break
            else:
                diffuse.append((i, c))
        diffuse.reverse()
        same_as = []
        for i, c in diffuse:
            for lnk in links:
                del lnk.args[i]
            v = block.inputargs.pop(i)
            same_as.append(SpaceOperation('same_as', [c], v))
            count += 1
        block.operations = same_as + block.operations
        if same_as:
            constant_fold_block(block)
    return count
예제 #22
0
def inputconst(reqtype, value):
    """Return a Constant with the given value, of the requested type,
    which can be a Repr instance or a low-level type.
    """
    if isinstance(reqtype, Repr):
        value = reqtype.convert_const(value)
        lltype = reqtype.lowleveltype
    elif isinstance(reqtype, LowLevelType):
        lltype = reqtype
    else:
        raise TypeError(repr(reqtype))
    if not lltype._contains_value(value):
        raise TyperError("inputconst(): expected a %r, got %r" %
                         (lltype, value))
    c = Constant(value)
    c.concretetype = lltype
    return c
예제 #23
0
    def test_frozen_user_class2(self):
        class C:
            def __add__(self, other):
                return 4
            def _freeze_(self):
                return True
        c = C()
        d = C()
        def f():
            return c+d
        graph = self.codetest(f)

        results = []
        for link in graph.iterlinks():
            if link.target == graph.returnblock:
                results.extend(link.args)
        assert results == [Constant(4)]
예제 #24
0
def test_join_blocks_cleans_links():
    from rpython.rtyper.lltypesystem import lltype
    from rpython.flowspace.model import Constant
    from rpython.translator.backendopt.removenoops import remove_same_as
    def f(x):
        return bool(x + 2)
    def g(x):
        if f(x):
            return 1
        else:
            return 2
    graph, t = translate(g, [int], backend_optimize=False)
    fgraph = graphof(t, f)
    fgraph.startblock.exits[0].args = [Constant(True, lltype.Bool)]
    # does not crash: previously join_blocks would barf on this
    remove_same_as(graph)
    backend_optimizations(t)
예제 #25
0
def insert_ll_stackcheck(translator):
    from rpython.translator.backendopt.support import find_calls_from
    from rpython.rlib.rstack import stack_check
    from rpython.tool.algo.graphlib import Edge, make_edge_dict, break_cycles_v
    rtyper = translator.rtyper
    graph = rtyper.annotate_helper(stack_check, [])
    rtyper.specialize_more_blocks()
    stack_check_ptr = rtyper.getcallable(graph)
    stack_check_ptr_const = Constant(stack_check_ptr,
                                     lltype.typeOf(stack_check_ptr))
    edges = set()
    insert_in = set()
    block2graph = {}
    for caller in translator.graphs:
        pyobj = getattr(caller, 'func', None)
        if pyobj is not None:
            if getattr(pyobj, '_dont_insert_stackcheck_', False):
                continue
        for block, callee in find_calls_from(translator, caller):
            if getattr(getattr(callee, 'func', None),
                       'insert_stack_check_here', False):
                insert_in.add(callee.startblock)
                block2graph[callee.startblock] = callee
                continue
            if block is not caller.startblock:
                edges.add((caller.startblock, block))
                block2graph[caller.startblock] = caller
            edges.add((block, callee.startblock))
            block2graph[block] = caller

    edgelist = [Edge(block1, block2) for (block1, block2) in edges]
    edgedict = make_edge_dict(edgelist)
    for block in break_cycles_v(edgedict, edgedict):
        insert_in.add(block)

    for block in insert_in:
        v = Variable()
        v.concretetype = lltype.Void
        unwind_op = SpaceOperation('direct_call', [stack_check_ptr_const], v)
        block.operations.insert(0, unwind_op)
        # prevents cycles of tail calls from occurring -- such cycles would
        # not consume any stack, so would turn into potentially infinite loops
        graph = block2graph[block]
        graph.inhibit_tail_call = True
    return len(insert_in)
예제 #26
0
파일: description.py 프로젝트: juokaz/pypy
    def add_source_attribute(self, name, value, mixin=False):
        if isinstance(value, types.FunctionType):
            # for debugging
            if not hasattr(value, 'class_'):
                value.class_ = self.pyobj
            if self.specialize:
                # make a custom funcdesc that specializes on its first
                # argument (i.e. 'self').
                from rpython.annotator.specialize import specialize_argtype

                def argtype0(funcdesc, args_s):
                    return specialize_argtype(funcdesc, args_s, 0)

                funcdesc = FunctionDesc(self.bookkeeper,
                                        value,
                                        specializer=argtype0)
                self.classdict[name] = funcdesc
                return
            if mixin:
                # make a new copy of the FunctionDesc for this class,
                # but don't specialize further for all subclasses
                funcdesc = FunctionDesc(self.bookkeeper, value)
                self.classdict[name] = funcdesc
                return
            # NB. if value is, say, AssertionError.__init__, then we
            # should not use getdesc() on it.  Never.  The problem is
            # that the py lib has its own AssertionError.__init__ which
            # is of type FunctionType.  But bookkeeper.immutablevalue()
            # will do the right thing in s_get_value().
        if isinstance(value, staticmethod) and mixin:
            # make a new copy of staticmethod
            func = value.__get__(42)
            value = staticmethod(func_with_new_name(func, func.__name__))

        if type(value) in MemberDescriptorTypes:
            # skip __slots__, showing up in the class as 'member' objects
            return
        if name == '__init__' and self.is_builtin_exception_class():
            # pretend that built-in exceptions have no __init__,
            # unless explicitly specified in builtin.py
            from rpython.annotator.builtin import BUILTIN_ANALYZERS
            value = getattr(value, 'im_func', value)
            if value not in BUILTIN_ANALYZERS:
                return
        self.classdict[name] = Constant(value)
예제 #27
0
파일: test_call.py 프로젝트: zielmicha/pypy
def test_graphs_from_indirect_call():
    cc = CallControl()
    F = lltype.FuncType([], lltype.Signed)
    v = varoftype(lltype.Signed)
    graphlst = ['f1graph', 'f2graph']
    op = SpaceOperation(
        'indirect_call',
        [varoftype(lltype.Ptr(F)),
         Constant(graphlst, lltype.Void)], v)
    #
    lst = cc.graphs_from(op, {'f1graph': True, 'f2graph': True}.__contains__)
    assert lst == ['f1graph', 'f2graph']  # normal indirect call
    #
    lst = cc.graphs_from(op, {'f1graph': True}.__contains__)
    assert lst == ['f1graph']  # indirect call, look only inside some graphs
    #
    lst = cc.graphs_from(op, {}.__contains__)
    assert lst is None  # indirect call, don't look inside any graph
예제 #28
0
 def test_regalloc_call(self):
     v1 = Variable(); v1.concretetype = lltype.Signed
     v2 = Variable(); v2.concretetype = lltype.Signed
     v3 = Variable(); v3.concretetype = lltype.Signed
     v4 = Variable(); v4.concretetype = lltype.Signed
     block = Block([v1])
     block.operations = [
         SpaceOperation('int_add', [v1, Constant(1, lltype.Signed)], v2),
         SpaceOperation('rescall', [ListOfKind('int', [v1, v2])], v3),
         ]
     graph = FunctionGraph('f', block, v4)
     block.closeblock(Link([v3], graph.returnblock))
     #
     self.check_assembler(graph, """
         int_add %i0, $1 -> %i1
         rescall I[%i0, %i1] -> %i0
         int_return %i0
     """)
예제 #29
0
 def rtype_simple_call(self, hop):
     # methods: look up the rtype_method_xxx()
     name = 'rtype_method_' + self.methodname
     try:
         bltintyper = getattr(self.self_repr, name)
     except AttributeError:
         raise TyperError("missing %s.%s" %
                          (self.self_repr.__class__.__name__, name))
     # hack based on the fact that 'lowleveltype == self_repr.lowleveltype'
     hop2 = hop.copy()
     assert hop2.args_r[0] is self
     if isinstance(hop2.args_v[0], Constant):
         c = hop2.args_v[0].value  # get object from bound method
         c = c.__self__
         hop2.args_v[0] = Constant(c)
     hop2.args_s[0] = self.s_self
     hop2.args_r[0] = self.self_repr
     return bltintyper(hop2)
예제 #30
0
 def make_exception_link(self, link, handling_ovf):
     # Like make_link(), but also introduces the 'last_exception' and
     # 'last_exc_value' as variables if needed.  Also check if the link
     # is jumping directly to the re-raising exception block.
     assert link.last_exception is not None
     assert link.last_exc_value is not None
     if link.target.operations == () and link.args == [link.last_exception,
                                                       link.last_exc_value]:
         if handling_ovf:
             exc_data = self.cpu.rtyper.exceptiondata
             ll_ovf = exc_data.get_standard_ll_exc_instance_by_class(
                 OverflowError)
             c = Constant(ll_ovf, concretetype=lltype.typeOf(ll_ovf))
             self.emitline("raise", c)
         else:
             self.emitline("reraise")
         self.emitline("---")
         return   # done
     self.make_link(link, handling_ovf)