コード例 #1
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_random_effects_on_stacklet_switch():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.translator.platform import CompilationError
    try:
        from rpython.rlib._rffi_stacklet import switch, handle
    except CompilationError as e:
        if "Unsupported platform!" in e.out:
            py.test.skip("Unsupported platform!")
        else:
            raise e

    @jit.dont_look_inside
    def f():
        switch(rffi.cast(handle, 0))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    op = block.operations[-1]
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
コード例 #2
0
ファイル: test_call.py プロジェクト: Qointum/pypy
def test_elidable_kinds():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    @jit.elidable
    def f1(n, m):
        return n + m
    @jit.elidable
    def f2(n, m):
        return [n, m]    # may raise MemoryError
    @jit.elidable
    def f3(n, m):
        if n > m:
            raise ValueError
        return n + m

    def f(n, m):
        a = f1(n, m)
        b = f2(n, m)
        c = f3(n, m)
        return a + len(b) + c

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]

    for index, expected in [
            (0, EffectInfo.EF_ELIDABLE_CANNOT_RAISE),
            (1, EffectInfo.EF_ELIDABLE_OR_MEMORYERROR),
            (2, EffectInfo.EF_ELIDABLE_CAN_RAISE)]:
        call_op = f_graph.startblock.operations[index]
        assert call_op.opname == 'direct_call'
        call_descr = cc.getcalldescr(call_op)
        assert call_descr.extrainfo.extraeffect == expected
コード例 #3
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_get_jitcode(monkeypatch):
    from rpython.jit.codewriter.test.test_flatten import FakeCPU

    class FakeRTyper:
        class annotator:
            translator = None

        class type_system:
            name = 'lltypesystem'

    def getfunctionptr(graph):
        F = lltype.FuncType([], lltype.Signed)
        return lltype.functionptr(F, 'bar')

    monkeypatch.setattr(call, 'getfunctionptr', getfunctionptr)
    cc = CallControl(FakeCPU(FakeRTyper()))

    class somegraph:
        name = "foo"

    jitcode = cc.get_jitcode(somegraph)
    assert jitcode is cc.get_jitcode(somegraph)  # caching
    assert jitcode.name == "foo"
    pending = list(cc.enum_pending_graphs())
    assert pending == [(somegraph, jitcode)]
コード例 #4
0
ファイル: test_call.py プロジェクト: mozillazg/pypy
def test_graphs_from_no_target():
    cc = CallControl()
    F = lltype.FuncType([], lltype.Signed)
    v = varoftype(lltype.Signed)
    op = SpaceOperation("indirect_call", [varoftype(lltype.Ptr(F)), Constant(None, lltype.Void)], v)
    lst = cc.graphs_from(op, {}.__contains__)
    assert lst is None
コード例 #5
0
ファイル: test_call.py プロジェクト: Qointum/pypy
def test_call_release_gil():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    T = rffi.CArrayPtr(rffi.TIME_T)
    external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True,
                               save_err=rffi.RFFI_SAVE_ERRNO)

    # no jit.dont_look_inside in this test
    def f():
        return external(lltype.nullptr(T.TO))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [llext_graph] = [x for x in res if x.func is external]
    [block, _] = list(llext_graph.iterblocks())
    [op] = block.operations
    tgt_tuple = op.args[0].value._obj.graph.func._call_aroundstate_target_
    assert type(tgt_tuple) is tuple and len(tgt_tuple) == 2
    call_target, saveerr = tgt_tuple
    assert saveerr == rffi.RFFI_SAVE_ERRNO
    call_target = llmemory.cast_ptr_to_adr(call_target)
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.is_call_release_gil() is True
    assert call_descr.extrainfo.call_release_gil_target == (
        call_target, rffi.RFFI_SAVE_ERRNO)
コード例 #6
0
ファイル: test_call.py プロジェクト: mozillazg/pypy
def test_can_or_cannot_collect():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    prebuilts = [[5], [6]]
    l = []

    def f1(n):
        if n > 1:
            raise IndexError
        return prebuilts[n]  # cannot collect

    f1._dont_inline_ = True

    def f2(n):
        return [n]  # can collect

    f2._dont_inline_ = True

    def f(n):
        a = f1(n)
        b = f2(n)
        return len(a) + len(b)

    rtyper = support.annotate(f, [1])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]
    for index, expected in [(0, False), (1, True), (2, False), (3, False)]:  # f1()  # f2()  # len()  # len()
        call_op = f_graph.startblock.operations[index]
        assert call_op.opname == "direct_call"
        call_descr = cc.getcalldescr(call_op)
        assert call_descr.extrainfo.check_can_collect() == expected
コード例 #7
0
ファイル: test_call.py プロジェクト: mozillazg/pypy
def test_random_effects_on_stacklet_switch():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.translator.platform import CompilationError

    try:
        from rpython.rlib._rffi_stacklet import switch, handle
    except CompilationError as e:
        if "Unsupported platform!" in e.out:
            py.test.skip("Unsupported platform!")
        else:
            raise e

    @jit.dont_look_inside
    def f():
        switch(rffi.cast(handle, 0))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    op = block.operations[-1]
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
コード例 #8
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_call_release_gil():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    T = rffi.CArrayPtr(rffi.TIME_T)
    external = rffi.llexternal("time", [T],
                               rffi.TIME_T,
                               releasegil=True,
                               save_err=rffi.RFFI_SAVE_ERRNO)

    # no jit.dont_look_inside in this test
    def f():
        return external(lltype.nullptr(T.TO))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [llext_graph] = [x for x in res if x.func is external]
    [block, _] = list(llext_graph.iterblocks())
    [op] = block.operations
    tgt_tuple = op.args[0].value._obj.graph.func._call_aroundstate_target_
    assert type(tgt_tuple) is tuple and len(tgt_tuple) == 2
    call_target, saveerr = tgt_tuple
    assert saveerr == rffi.RFFI_SAVE_ERRNO
    call_target = llmemory.cast_ptr_to_adr(call_target)
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.is_call_release_gil() is True
    assert call_descr.extrainfo.call_release_gil_target == (
        call_target, rffi.RFFI_SAVE_ERRNO)
コード例 #9
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_graphs_from_no_target():
    cc = CallControl()
    F = lltype.FuncType([], lltype.Signed)
    v = varoftype(lltype.Signed)
    op = SpaceOperation(
        'indirect_call',
        [varoftype(lltype.Ptr(F)),
         Constant(None, lltype.Void)], v)
    lst = cc.graphs_from(op, {}.__contains__)
    assert lst is None
コード例 #10
0
def test_find_all_graphs():
    def g(x):
        return x + 2
    def f(x):
        return g(x) + 1
    rtyper = support.annotate(f, [7])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    funcs = set([graph.func for graph in res])
    assert funcs == set([f, g])
コード例 #11
0
def test_graphs_from_direct_call():
    cc = CallControl()
    F = lltype.FuncType([], lltype.Signed)
    f = lltype.functionptr(F, 'f', graph='fgraph')
    v = varoftype(lltype.Signed)
    op = SpaceOperation('direct_call', [Constant(f, lltype.Ptr(F))], v)
    #
    lst = cc.graphs_from(op, {}.__contains__)
    assert lst is None     # residual call
    #
    lst = cc.graphs_from(op, {'fgraph': True}.__contains__)
    assert lst == ['fgraph']     # normal call
コード例 #12
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_graphs_from_direct_call():
    cc = CallControl()
    F = lltype.FuncType([], lltype.Signed)
    f = lltype.functionptr(F, 'f', graph='fgraph')
    v = varoftype(lltype.Signed)
    op = SpaceOperation('direct_call', [Constant(f, lltype.Ptr(F))], v)
    #
    lst = cc.graphs_from(op, {}.__contains__)
    assert lst is None  # residual call
    #
    lst = cc.graphs_from(op, {'fgraph': True}.__contains__)
    assert lst == ['fgraph']  # normal call
コード例 #13
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_find_all_graphs():
    def g(x):
        return x + 2

    def f(x):
        return g(x) + 1

    rtyper = support.annotate(f, [7])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    funcs = set([graph.func for graph in res])
    assert funcs == set([f, g])
コード例 #14
0
def test_find_all_graphs_without_g():
    def g(x):
        return x + 2
    def f(x):
        return g(x) + 1
    rtyper = support.annotate(f, [7])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(jitdrivers_sd=[jitdriver_sd])
    class CustomFakePolicy:
        def look_inside_graph(self, graph):
            assert graph.name == 'g'
            return False
    res = cc.find_all_graphs(CustomFakePolicy())
    funcs = [graph.func for graph in res]
    assert funcs == [f]
コード例 #15
0
ファイル: test_call.py プロジェクト: mozillazg/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
コード例 #16
0
def test_elidable_kinds():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.rlib.objectmodel import compute_hash
    from rpython.rlib.rsiphash import enable_siphash24

    @jit.elidable
    def f1(n, m):
        return n + m

    @jit.elidable
    def f2(n, m):
        return [n, m]  # may raise MemoryError

    @jit.elidable
    def f3(n, m):
        if n > m:
            raise ValueError
        return n + m

    @jit.elidable
    def f4(n, m):
        return compute_hash(str(n) + str(m))

    def f(n, m):
        a = f1(n, m)
        b = f2(n, m)
        c = f3(n, m)
        d = f4(n, m)
        enable_siphash24()
        return a + len(b) + c + d

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]

    for index, expected in [(0, EffectInfo.EF_ELIDABLE_CANNOT_RAISE),
                            (1, EffectInfo.EF_ELIDABLE_OR_MEMORYERROR),
                            (2, EffectInfo.EF_ELIDABLE_CAN_RAISE),
                            (3, EffectInfo.EF_ELIDABLE_OR_MEMORYERROR)]:
        call_op = f_graph.startblock.operations[index]
        assert call_op.opname == 'direct_call'
        call_descr = cc.getcalldescr(call_op)
        assert call_descr.extrainfo.extraeffect == expected
コード例 #17
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
コード例 #18
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_find_all_graphs_without_g():
    def g(x):
        return x + 2

    def f(x):
        return g(x) + 1

    rtyper = support.annotate(f, [7])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(jitdrivers_sd=[jitdriver_sd])

    class CustomFakePolicy:
        def look_inside_graph(self, graph):
            assert graph.name == 'g'
            return False

    res = cc.find_all_graphs(CustomFakePolicy())
    funcs = [graph.func for graph in res]
    assert funcs == [f]
コード例 #19
0
ファイル: test_call.py プロジェクト: Qointum/pypy
def test_raise_elidable_no_result():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    l = []
    @jit.elidable
    def f1(n, m):
        l.append(n)
    def f(n, m):
        f1(n, m)
        return n + m

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]
    call_op = f_graph.startblock.operations[0]
    assert call_op.opname == 'direct_call'
    with py.test.raises(Exception):
        call_descr = cc.getcalldescr(call_op)
コード例 #20
0
ファイル: test_call.py プロジェクト: abhinavthomas/pypy
def test_get_jitcode(monkeypatch):
    from rpython.jit.codewriter.test.test_flatten import FakeCPU
    class FakeRTyper:
        class annotator:
            translator = None

    def getfunctionptr(graph):
        F = lltype.FuncType([], lltype.Signed)
        return lltype.functionptr(F, 'bar')

    monkeypatch.setattr(call, 'getfunctionptr', getfunctionptr)
    cc = CallControl(FakeCPU(FakeRTyper()))
    class somegraph:
        name = "foo"
    jitcode = cc.get_jitcode(somegraph)
    assert jitcode is cc.get_jitcode(somegraph)    # caching
    assert jitcode.name == "foo"
    pending = list(cc.enum_pending_graphs())
    assert pending == [(somegraph, jitcode)]
コード例 #21
0
def test_get_jitcode():
    from rpython.jit.codewriter.test.test_flatten import FakeCPU
    class FakeRTyper:
        class annotator:
            translator = None
        class type_system:
            name = 'lltypesystem'
            @staticmethod
            def getcallable(graph):
                F = lltype.FuncType([], lltype.Signed)
                return lltype.functionptr(F, 'bar')
    #
    cc = CallControl(FakeCPU(FakeRTyper()))
    class somegraph:
        name = "foo"
    jitcode = cc.get_jitcode(somegraph)
    assert jitcode is cc.get_jitcode(somegraph)    # caching
    assert jitcode.name == "foo"
    pending = list(cc.enum_pending_graphs())
    assert pending == [(somegraph, jitcode)]
コード例 #22
0
def test_raise_elidable_no_result():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    l = []

    @jit.elidable
    def f1(n, m):
        l.append(n)

    def f(n, m):
        f1(n, m)
        return n + m

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]
    call_op = f_graph.startblock.operations[0]
    assert call_op.opname == 'direct_call'
    with py.test.raises(Exception):
        call_descr = cc.getcalldescr(call_op)
コード例 #23
0
def test_releases_gil_analyzer():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    T = rffi.CArrayPtr(rffi.TIME_T)
    external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True)

    @jit.dont_look_inside
    def f():
        return external(lltype.nullptr(T.TO))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    [op] = block.operations
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.is_call_release_gil() is False
コード例 #24
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_releases_gil_analyzer():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU

    T = rffi.CArrayPtr(rffi.TIME_T)
    external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True)

    @jit.dont_look_inside
    def f():
        return external(lltype.nullptr(T.TO))

    rtyper = support.annotate(f, [])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    [op] = block.operations
    call_descr = cc.getcalldescr(op)
    assert call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.is_call_release_gil() is False
コード例 #25
0
def test_no_random_effects_for_rotateLeft():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.rlib.rarithmetic import r_uint

    if r_uint.BITS == 32:
        py.test.skip("64-bit only")

    from rpython.rlib.rmd5 import _rotateLeft
    def f(n, m):
        return _rotateLeft(r_uint(n), m)

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    op = block.operations[-1]
    call_descr = cc.getcalldescr(op)
    assert not call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.check_is_elidable()
コード例 #26
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_no_random_effects_for_rotateLeft():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.rlib.rarithmetic import r_uint

    if r_uint.BITS == 32:
        py.test.skip("64-bit only")

    from rpython.rlib.rmd5 import _rotateLeft

    def f(n, m):
        return _rotateLeft(r_uint(n), m)

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())

    [f_graph] = [x for x in res if x.func is f]
    [block, _] = list(f_graph.iterblocks())
    op = block.operations[-1]
    call_descr = cc.getcalldescr(op)
    assert not call_descr.extrainfo.has_random_effects()
    assert call_descr.extrainfo.check_is_elidable()
コード例 #27
0
def test_can_or_cannot_collect():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    prebuilts = [[5], [6]]
    l = []

    def f1(n):
        if n > 1:
            raise IndexError
        return prebuilts[n]  # cannot collect

    f1._dont_inline_ = True

    def f2(n):
        return [n]  # can collect

    f2._dont_inline_ = True

    def f(n):
        a = f1(n)
        b = f2(n)
        return len(a) + len(b)

    rtyper = support.annotate(f, [1])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]
    for index, expected in [
        (0, False),  # f1()
        (1, True),  # f2()
        (2, False),  # len()
        (3, False)
    ]:  # len()
        call_op = f_graph.startblock.operations[index]
        assert call_op.opname == 'direct_call'
        call_descr = cc.getcalldescr(call_op)
        assert call_descr.extrainfo.check_can_collect() == expected
コード例 #28
0
ファイル: codewriter.py プロジェクト: Mu-L/pypy
class CodeWriter(object):
    callcontrol = None  # for tests
    debug = True

    def __init__(self, cpu=None, jitdrivers_sd=[]):
        self.cpu = cpu
        self.assembler = Assembler()
        self.callcontrol = CallControl(cpu, jitdrivers_sd)

    def transform_func_to_jitcode(self, func, values):
        """For testing."""
        rtyper = support.annotate(func, values)
        graph = rtyper.annotator.translator.graphs[0]
        jitcode = JitCode("test")
        self.transform_graph_to_jitcode(graph, jitcode, True, 0)
        return jitcode

    def transform_graph_to_jitcode(self, graph, jitcode, verbose, index):
        """Transform a graph into a JitCode containing the same bytecode
        in a different format.
        """
        portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph)
        graph = copygraph(graph, shallowvars=True)
        #
        # step 1: mangle the graph so that it contains the final instructions
        # that we want in the JitCode, but still as a control flow graph
        transform_graph(graph, self.cpu, self.callcontrol, portal_jd)
        #
        # step 2: perform register allocation on it
        regallocs = {}
        for kind in KINDS:
            regallocs[kind] = perform_register_allocation(graph, kind)
        #
        # step 3: flatten the graph to produce human-readable "assembler",
        # which means mostly producing a linear list of operations and
        # inserting jumps or conditional jumps.  This is a list of tuples
        # of the shape ("opname", arg1, ..., argN) or (Label(...),).
        ssarepr = flatten_graph(graph, regallocs, cpu=self.callcontrol.cpu)
        #
        # step 3b: compute the liveness around certain operations
        compute_liveness(ssarepr)
        #
        # step 4: "assemble" it into a JitCode, which contains a sequence
        # of bytes and lists of constants.  It's during this step that
        # constants are cast to their normalized type (Signed, GCREF or
        # Float).
        self.assembler.assemble(ssarepr, jitcode)
        jitcode.index = index
        #
        # print the resulting assembler
        if self.debug:
            self.print_ssa_repr(ssarepr, portal_jd, verbose)

    def make_jitcodes(self, verbose=False):
        log.info("making JitCodes...")
        self.callcontrol.grab_initial_jitcodes()
        count = 0
        all_jitcodes = []
        for graph, jitcode in self.callcontrol.enum_pending_graphs():
            self.transform_graph_to_jitcode(graph, jitcode, verbose,
                                            len(all_jitcodes))
            all_jitcodes.append(jitcode)
            count += 1
            if not count % 500:
                log.info("Produced %d jitcodes" % count)
        self.assembler.finished(self.callcontrol.callinfocollection)
        log.info("There are %d JitCode instances." % count)
        log.info("There are %d -live- ops. Size of liveness is %s bytes" %
                 (self.assembler.num_liveness_ops,
                  self.assembler.all_liveness_length))
        return all_jitcodes

    def setup_vrefinfo(self, vrefinfo):
        # must be called at most once
        assert self.callcontrol.virtualref_info is None
        self.callcontrol.virtualref_info = vrefinfo

    def setup_jitdriver(self, jitdriver_sd):
        # Must be called once per jitdriver.  Usually jitdriver_sd is an
        # instance of rpython.jit.metainterp.jitdriver.JitDriverStaticData.
        self.callcontrol.jitdrivers_sd.append(jitdriver_sd)

    def find_all_graphs(self, policy):
        return self.callcontrol.find_all_graphs(policy)

    def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose):
        if verbose:
            print '%s:' % (ssarepr.name, )
            print format_assembler(ssarepr)
        else:
            log.dot()
        dir = udir.ensure("jitcodes", dir=1)
        if portal_jitdriver:
            name = "%02d_portal_runner" % (portal_jitdriver.index, )
        elif ssarepr.name and ssarepr.name != '?':
            name = ssarepr.name
        else:
            name = 'unnamed' % id(ssarepr)
        i = 1
        # escape names like <lambda> for windows by removing any strange
        # character; then make sure the names are not too long
        name = ''.join(c for c in name if c.isalnum() or c == '_')[:60]
        extra = ''
        while dir.join(name + extra).check():
            i += 1
            extra = '.%d' % i
        dir.join(name + extra).write(format_assembler(ssarepr))
コード例 #29
0
ファイル: codewriter.py プロジェクト: Mu-L/pypy
 def __init__(self, cpu=None, jitdrivers_sd=[]):
     self.cpu = cpu
     self.assembler = Assembler()
     self.callcontrol = CallControl(cpu, jitdrivers_sd)
コード例 #30
0
def test_elidable_kinds():
    from rpython.jit.backend.llgraph.runner import LLGraphCPU
    from rpython.rlib.objectmodel import compute_hash
    from rpython.rlib.rsiphash import enable_siphash24

    @jit.elidable
    def f1(n, m):
        return n + m

    @jit.elidable
    def f2(n, m):
        return [n, m]  # may raise MemoryError

    @jit.elidable
    def f3(n, m):
        if n > m:
            raise ValueError
        return n + m

    @jit.elidable
    def f4(n, m):
        return compute_hash(str(n) + str(m))

    T = rffi.CArrayPtr(rffi.TIME_T)
    external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True)

    def effect():
        return external(lltype.nullptr(T.TO))

    @jit.elidable
    def f5(n, m):
        effect()
        return 1

    def f(n, m):
        a = f1(n, m)
        b = f2(n, m)
        c = f3(n, m)
        d = f4(n, m)
        f5(n, m)
        enable_siphash24()
        return a + len(b) + c + d

    rtyper = support.annotate(f, [7, 9])
    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
    cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
    res = cc.find_all_graphs(FakePolicy())
    [f_graph] = [x for x in res if x.func is f]

    for index, expected in [(0, EffectInfo.EF_ELIDABLE_CANNOT_RAISE),
                            (1, EffectInfo.EF_ELIDABLE_OR_MEMORYERROR),
                            (2, EffectInfo.EF_ELIDABLE_CAN_RAISE),
                            (3, EffectInfo.EF_ELIDABLE_OR_MEMORYERROR)]:
        call_op = f_graph.startblock.operations[index]
        assert call_op.opname == 'direct_call'
        call_descr = cc.getcalldescr(call_op)
        assert call_descr.extrainfo.extraeffect == expected

    call_op = f_graph.startblock.operations[4]
    assert call_op.opname == 'direct_call'
    excinfo = py.test.raises(Exception, cc.getcalldescr, call_op)
    lines = excinfo.value.args[0].splitlines()
    assert "f5" in lines[2]
    assert "effect" in lines[3]
    assert "random effects" in lines[-1]
コード例 #31
0
ファイル: test_call.py プロジェクト: zielmicha/pypy
def test_guess_call_kind_and_calls_from_graphs():
    class portal_runner_obj:
        graph = object()

    class FakeJitDriverSD:
        portal_runner_ptr = portal_runner_obj

    g = object()
    g1 = object()
    cc = CallControl(jitdrivers_sd=[FakeJitDriverSD()])
    cc.candidate_graphs = [g, g1]

    op = SpaceOperation('direct_call', [Constant(portal_runner_obj)],
                        Variable())
    assert cc.guess_call_kind(op) == 'recursive'

    class fakeresidual:
        _obj = object()

    op = SpaceOperation('direct_call', [Constant(fakeresidual)], Variable())
    assert cc.guess_call_kind(op) == 'residual'

    class funcptr:
        class _obj:
            class graph:
                class func:
                    oopspec = "spec"

    op = SpaceOperation('direct_call', [Constant(funcptr)], Variable())
    assert cc.guess_call_kind(op) == 'builtin'

    class funcptr:
        class _obj:
            graph = g

    op = SpaceOperation('direct_call', [Constant(funcptr)], Variable())
    res = cc.graphs_from(op)
    assert res == [g]
    assert cc.guess_call_kind(op) == 'regular'

    class funcptr:
        class _obj:
            graph = object()

    op = SpaceOperation('direct_call', [Constant(funcptr)], Variable())
    res = cc.graphs_from(op)
    assert res is None
    assert cc.guess_call_kind(op) == 'residual'

    h = object()
    op = SpaceOperation('indirect_call',
                        [Variable(), Constant([g, g1, h])], Variable())
    res = cc.graphs_from(op)
    assert res == [g, g1]
    assert cc.guess_call_kind(op) == 'regular'

    op = SpaceOperation('indirect_call',
                        [Variable(), Constant([h])], Variable())
    res = cc.graphs_from(op)
    assert res is None
    assert cc.guess_call_kind(op) == 'residual'
コード例 #32
0
ファイル: codewriter.py プロジェクト: Darriall/pypy
 def __init__(self, cpu=None, jitdrivers_sd=[]):
     self.cpu = cpu
     self.assembler = Assembler()
     self.callcontrol = CallControl(cpu, jitdrivers_sd)
     self._seen_files = set()
コード例 #33
0
ファイル: codewriter.py プロジェクト: Darriall/pypy
class CodeWriter(object):
    callcontrol = None    # for tests
    debug = True

    def __init__(self, cpu=None, jitdrivers_sd=[]):
        self.cpu = cpu
        self.assembler = Assembler()
        self.callcontrol = CallControl(cpu, jitdrivers_sd)
        self._seen_files = set()

    def transform_func_to_jitcode(self, func, values):
        """For testing."""
        rtyper = support.annotate(func, values)
        graph = rtyper.annotator.translator.graphs[0]
        jitcode = JitCode("test")
        self.transform_graph_to_jitcode(graph, jitcode, True)
        return jitcode

    def transform_graph_to_jitcode(self, graph, jitcode, verbose):
        """Transform a graph into a JitCode containing the same bytecode
        in a different format.
        """
        portal_jd = self.callcontrol.jitdriver_sd_from_portal_graph(graph)
        graph = copygraph(graph, shallowvars=True)
        #
        # step 1: mangle the graph so that it contains the final instructions
        # that we want in the JitCode, but still as a control flow graph
        transform_graph(graph, self.cpu, self.callcontrol, portal_jd)
        #
        # step 2: perform register allocation on it
        regallocs = {}
        for kind in KINDS:
            regallocs[kind] = perform_register_allocation(graph, kind)
        #
        # step 3: flatten the graph to produce human-readable "assembler",
        # which means mostly producing a linear list of operations and
        # inserting jumps or conditional jumps.  This is a list of tuples
        # of the shape ("opname", arg1, ..., argN) or (Label(...),).
        ssarepr = flatten_graph(graph, regallocs)
        #
        # step 3b: compute the liveness around certain operations
        compute_liveness(ssarepr)
        #
        # step 4: "assemble" it into a JitCode, which contains a sequence
        # of bytes and lists of constants.  It's during this step that
        # constants are cast to their normalized type (Signed, GCREF or
        # Float).
        self.assembler.assemble(ssarepr, jitcode)
        #
        # print the resulting assembler
        if self.debug:
            self.print_ssa_repr(ssarepr, portal_jd, verbose)

    def make_jitcodes(self, verbose=False):
        log.info("making JitCodes...")
        self.callcontrol.grab_initial_jitcodes()
        count = 0
        for graph, jitcode in self.callcontrol.enum_pending_graphs():
            self.transform_graph_to_jitcode(graph, jitcode, verbose)
            count += 1
            if not count % 500:
                log.info("Produced %d jitcodes" % count)
        self.assembler.finished(self.callcontrol.callinfocollection)
        heaptracker.finish_registering(self.cpu)
        log.info("there are %d JitCode instances." % count)

    def setup_vrefinfo(self, vrefinfo):
        # must be called at most once
        assert self.callcontrol.virtualref_info is None
        self.callcontrol.virtualref_info = vrefinfo

    def setup_jitdriver(self, jitdriver_sd):
        # Must be called once per jitdriver.  Usually jitdriver_sd is an
        # instance of rpython.jit.metainterp.jitdriver.JitDriverStaticData.
        self.callcontrol.jitdrivers_sd.append(jitdriver_sd)

    def find_all_graphs(self, policy):
        return self.callcontrol.find_all_graphs(policy)

    def print_ssa_repr(self, ssarepr, portal_jitdriver, verbose):
        if verbose:
            print '%s:' % (ssarepr.name,)
            print format_assembler(ssarepr)
        else:
            log.dot()
        dir = udir.ensure("jitcodes", dir=1)
        if portal_jitdriver:
            name = "%02d_portal_runner" % (portal_jitdriver.index,)
        elif ssarepr.name and ssarepr.name != '?':
            name = ssarepr.name
        else:
            name = 'unnamed' % id(ssarepr)
        i = 1
        # escape <lambda> names for windows
        name = name.replace('<lambda>', '_(lambda)_')
        extra = ''
        while name+extra in self._seen_files:
            i += 1
            extra = '.%d' % i
        self._seen_files.add(name+extra)
        dir.join(name+extra).write(format_assembler(ssarepr))
コード例 #34
0
def test_guess_call_kind_and_calls_from_graphs():
    class portal_runner_obj:
        graph = object()
    class FakeJitDriverSD:
        portal_runner_ptr = portal_runner_obj
    g = object()
    g1 = object()
    cc = CallControl(jitdrivers_sd=[FakeJitDriverSD()])
    cc.candidate_graphs = [g, g1]

    op = SpaceOperation('direct_call', [Constant(portal_runner_obj)],
                        Variable())
    assert cc.guess_call_kind(op) == 'recursive'

    class fakeresidual:
        _obj = object()
    op = SpaceOperation('direct_call', [Constant(fakeresidual)],
                        Variable())
    assert cc.guess_call_kind(op) == 'residual'

    class funcptr:
        class _obj:
            class graph:
                class func:
                    oopspec = "spec"
    op = SpaceOperation('direct_call', [Constant(funcptr)],
                        Variable())
    assert cc.guess_call_kind(op) == 'builtin'

    class funcptr:
        class _obj:
            graph = g
    op = SpaceOperation('direct_call', [Constant(funcptr)],
                        Variable())
    res = cc.graphs_from(op)
    assert res == [g]
    assert cc.guess_call_kind(op) == 'regular'

    class funcptr:
        class _obj:
            graph = object()
    op = SpaceOperation('direct_call', [Constant(funcptr)],
                        Variable())
    res = cc.graphs_from(op)
    assert res is None
    assert cc.guess_call_kind(op) == 'residual'

    h = object()
    op = SpaceOperation('indirect_call', [Variable(),
                                          Constant([g, g1, h])],
                        Variable())
    res = cc.graphs_from(op)
    assert res == [g, g1]
    assert cc.guess_call_kind(op) == 'regular'

    op = SpaceOperation('indirect_call', [Variable(),
                                          Constant([h])],
                        Variable())
    res = cc.graphs_from(op)
    assert res is None
    assert cc.guess_call_kind(op) == 'residual'