コード例 #1
0
    def __init__(self,
                 translator,
                 policy=None,
                 backendopt=True,
                 CPUClass=None,
                 ProfilerClass=EmptyProfiler,
                 **kwds):
        pyjitpl._warmrunnerdesc = self  # this is a global for debugging only!
        self.set_translator(translator)
        self.memory_manager = memmgr.MemoryManager()
        self.build_cpu(CPUClass, **kwds)
        self.inline_inlineable_portals()
        self.find_portals()
        self.codewriter = codewriter.CodeWriter(self.cpu, self.jitdrivers_sd)
        if policy is None:
            policy = JitPolicy()
        policy.set_supports_floats(self.cpu.supports_floats)
        policy.set_supports_longlong(self.cpu.supports_longlong)
        policy.set_supports_singlefloats(self.cpu.supports_singlefloats)
        graphs = self.codewriter.find_all_graphs(policy)
        policy.dump_unsafe_loops()
        self.check_access_directly_sanity(graphs)
        if backendopt:
            self.prejit_optimizations(policy, graphs)
        elif self.opt.listops:
            self.prejit_optimizations_minimal_inline(policy, graphs)

        self.build_meta_interp(
            ProfilerClass, translator.config.translation.jit_opencoder_model)
        self.make_args_specifications()
        #
        from rpython.jit.metainterp.virtualref import VirtualRefInfo
        vrefinfo = VirtualRefInfo(self)
        self.codewriter.setup_vrefinfo(vrefinfo)
        #
        from rpython.jit.metainterp import counter
        if self.cpu.translate_support_code:
            self.jitcounter = counter.JitCounter(translator=translator)
        else:
            self.jitcounter = counter.DeterministicJitCounter()
        #
        self.hooks = policy.jithookiface
        self.make_virtualizable_infos()
        self.make_driverhook_graphs()
        self.make_enter_functions()
        self.rewrite_jit_merge_points(policy)

        verbose = False  # not self.cpu.translate_support_code
        self.rewrite_access_helpers()
        self.create_jit_entry_points()
        jitcodes = self.codewriter.make_jitcodes(verbose=verbose)
        self.metainterp_sd.jitcodes = jitcodes
        self.rewrite_can_enter_jits()
        self.rewrite_set_param_and_get_stats()
        self.rewrite_force_virtual(vrefinfo)
        self.rewrite_jitcell_accesses()
        self.rewrite_force_quasi_immutable()
        self.add_finish()
        self.metainterp_sd.finish_setup(self.codewriter)
コード例 #2
0
ファイル: test_util.py プロジェクト: zcxowwww/pypy
class LLtypeMixin(object):
    node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    node_vtable.name = rclass.alloc_array_name('node')
    node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True)
    node_vtable2.name = rclass.alloc_array_name('node2')
    node_vtable3 = lltype.malloc(OBJECT_VTABLE, immortal=True)
    node_vtable3.name = rclass.alloc_array_name('node3')
    node_vtable3.subclassrange_min = 3
    node_vtable3.subclassrange_max = 3
    cpu = runner.LLGraphCPU(None)

    NODE = lltype.GcForwardReference()
    S = lltype.GcForwardReference()
    NODE.become(
        lltype.GcStruct('NODE', ('parent', OBJECT), ('value', lltype.Signed),
                        ('floatval', lltype.Float), ('charval', lltype.Char),
                        ('nexttuple', lltype.Ptr(S)),
                        ('next', lltype.Ptr(NODE))))
    S.become(
        lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('abis', lltype.Signed),
                        ('b', lltype.Ptr(NODE))))
    NODE2 = lltype.GcStruct('NODE2', ('parent', NODE),
                            ('other', lltype.Ptr(NODE)))

    NODE3 = lltype.GcForwardReference()
    NODE3.become(
        lltype.GcStruct('NODE3', ('parent', OBJECT), ('value', lltype.Signed),
                        ('next', lltype.Ptr(NODE3)),
                        hints={'immutable': True}))

    big_fields = [('big' + i, lltype.Signed) for i in string.ascii_lowercase]
    BIG = lltype.GcForwardReference()
    BIG.become(lltype.GcStruct('BIG', *big_fields, hints={'immutable': True}))

    for field, _ in big_fields:
        locals()[field + 'descr'] = cpu.fielddescrof(BIG, field)

    node = lltype.malloc(NODE)
    node.value = 5
    node.next = node
    node.parent.typeptr = node_vtable
    nodeaddr = lltype.cast_opaque_ptr(llmemory.GCREF, node)
    #nodebox = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, node))
    node2 = lltype.malloc(NODE2)
    node2.parent.parent.typeptr = node_vtable2
    node2addr = lltype.cast_opaque_ptr(llmemory.GCREF, node2)
    myptr = lltype.cast_opaque_ptr(llmemory.GCREF, node)
    mynodeb = lltype.malloc(NODE)
    myarray = lltype.cast_opaque_ptr(
        llmemory.GCREF,
        lltype.malloc(lltype.GcArray(lltype.Signed), 13, zero=True))
    mynodeb.parent.typeptr = node_vtable
    myptrb = lltype.cast_opaque_ptr(llmemory.GCREF, mynodeb)
    myptr2 = lltype.malloc(NODE2)
    myptr2.parent.parent.typeptr = node_vtable2
    myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, myptr2)
    nullptr = lltype.nullptr(llmemory.GCREF.TO)

    mynode3 = lltype.malloc(NODE3)
    mynode3.parent.typeptr = node_vtable3
    mynode3.value = 7
    mynode3.next = mynode3
    myptr3 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode3)  # a NODE2
    mynode4 = lltype.malloc(NODE3)
    mynode4.parent.typeptr = node_vtable3
    myptr4 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode4)  # a NODE3

    nodesize = cpu.sizeof(NODE, node_vtable)
    node_tid = nodesize.get_type_id()
    nodesize2 = cpu.sizeof(NODE2, node_vtable2)
    nodesize3 = cpu.sizeof(NODE3, node_vtable3)
    valuedescr = cpu.fielddescrof(NODE, 'value')
    floatdescr = cpu.fielddescrof(NODE, 'floatval')
    chardescr = cpu.fielddescrof(NODE, 'charval')
    nextdescr = cpu.fielddescrof(NODE, 'next')
    nexttupledescr = cpu.fielddescrof(NODE, 'nexttuple')
    otherdescr = cpu.fielddescrof(NODE2, 'other')
    valuedescr3 = cpu.fielddescrof(NODE3, 'value')
    nextdescr3 = cpu.fielddescrof(NODE3, 'next')
    assert valuedescr3.is_always_pure()
    assert nextdescr3.is_always_pure()

    accessor = FieldListAccessor()
    accessor.initialize(None, {'inst_field': IR_QUASIIMMUTABLE})
    QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
                            ('mutate_field', rclass.OBJECTPTR),
                            hints={'immutable_fields': accessor})
    quasisize = cpu.sizeof(QUASI, None)
    quasi = lltype.malloc(QUASI, immortal=True)
    quasi.inst_field = -4247
    quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
    quasiptr = lltype.cast_opaque_ptr(llmemory.GCREF, quasi)
    quasiimmutdescr = QuasiImmutDescr(cpu, quasiptr, quasifielddescr,
                                      cpu.fielddescrof(QUASI, 'mutate_field'))

    NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT),
                              ('ref', lltype.Ptr(OBJECT)))
    nodeobj = lltype.malloc(NODEOBJ)
    nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
    refdescr = cpu.fielddescrof(NODEOBJ, 'ref')

    INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT),
                                     ('intval', lltype.Signed))
    INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT),
                                   ('intval', lltype.Signed),
                                   hints={'immutable': True})
    intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
    immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
    immut = lltype.malloc(INTOBJ_IMMUT, zero=True)
    immutaddr = lltype.cast_opaque_ptr(llmemory.GCREF, immut)
    noimmut_descr = cpu.sizeof(INTOBJ_NOIMMUT, intobj_noimmut_vtable)
    immut_descr = cpu.sizeof(INTOBJ_IMMUT, intobj_immut_vtable)

    PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT),
                                   ('ptrval', lltype.Ptr(OBJECT)),
                                   hints={'immutable': True})
    ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    ptrobj_immut_descr = cpu.sizeof(PTROBJ_IMMUT, ptrobj_immut_vtable)
    immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval')

    arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
    int32arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.INT))
    int16arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.SHORT))
    float32arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.SingleFloat))
    arraydescr_tid = arraydescr.get_type_id()
    array = lltype.malloc(lltype.GcArray(lltype.Signed), 15, zero=True)
    arrayref = lltype.cast_opaque_ptr(llmemory.GCREF, array)
    array2 = lltype.malloc(lltype.GcArray(lltype.Ptr(S)), 15, zero=True)
    array2ref = lltype.cast_opaque_ptr(llmemory.GCREF, array2)
    gcarraydescr = cpu.arraydescrof(lltype.GcArray(llmemory.GCREF))
    gcarraydescr_tid = gcarraydescr.get_type_id()
    floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))

    arrayimmutdescr = cpu.arraydescrof(
        lltype.GcArray(lltype.Signed, hints={"immutable": True}))
    immutarray = lltype.cast_opaque_ptr(
        llmemory.GCREF, lltype.malloc(arrayimmutdescr.A, 13, zero=True))
    gcarrayimmutdescr = cpu.arraydescrof(
        lltype.GcArray(llmemory.GCREF, hints={"immutable": True}))
    floatarrayimmutdescr = cpu.arraydescrof(
        lltype.GcArray(lltype.Float, hints={"immutable": True}))

    # a GcStruct not inheriting from OBJECT
    tpl = lltype.malloc(S, zero=True)
    tupleaddr = lltype.cast_opaque_ptr(llmemory.GCREF, tpl)
    nodefull2 = lltype.malloc(NODE, zero=True)
    nodefull2addr = lltype.cast_opaque_ptr(llmemory.GCREF, nodefull2)
    ssize = cpu.sizeof(S, None)
    adescr = cpu.fielddescrof(S, 'a')
    abisdescr = cpu.fielddescrof(S, 'abis')
    bdescr = cpu.fielddescrof(S, 'b')
    #sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)))
    arraydescr2 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(S)))

    T = lltype.GcStruct('TUPLE', ('c', lltype.Signed),
                        ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))

    W_ROOT = lltype.GcStruct(
        'W_ROOT', ('parent', OBJECT), ('inst_w_seq', llmemory.GCREF),
        ('inst_index', lltype.Signed), ('inst_w_list', llmemory.GCREF),
        ('inst_length', lltype.Signed), ('inst_start', lltype.Signed),
        ('inst_step', lltype.Signed))
    inst_w_seq = cpu.fielddescrof(W_ROOT, 'inst_w_seq')
    inst_index = cpu.fielddescrof(W_ROOT, 'inst_index')
    inst_length = cpu.fielddescrof(W_ROOT, 'inst_length')
    inst_start = cpu.fielddescrof(W_ROOT, 'inst_start')
    inst_step = cpu.fielddescrof(W_ROOT, 'inst_step')
    inst_w_list = cpu.fielddescrof(W_ROOT, 'inst_w_list')
    w_root_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)

    tsize = cpu.sizeof(T, None)
    cdescr = cpu.fielddescrof(T, 'c')
    ddescr = cpu.fielddescrof(T, 'd')
    arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE3)))

    U = lltype.GcStruct('U', ('parent', OBJECT),
                        ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
    u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    SIMPLE = lltype.GcStruct('simple', ('parent', OBJECT),
                             ('value', lltype.Signed))
    simplevalue = cpu.fielddescrof(SIMPLE, 'value')
    simple_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    simpledescr = cpu.sizeof(SIMPLE, simple_vtable)
    simple = lltype.malloc(SIMPLE, zero=True)
    simpleaddr = lltype.cast_opaque_ptr(llmemory.GCREF, simple)
    #usize = cpu.sizeof(U, ...)
    onedescr = cpu.fielddescrof(U, 'one')

    FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
    plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                     EffectInfo.MOST_GENERAL)
    elidablecalldescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([valuedescr], [], [], [valuedescr], [], [],
                   EffectInfo.EF_ELIDABLE_CANNOT_RAISE))
    elidable2calldescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([valuedescr], [], [], [valuedescr], [], [],
                   EffectInfo.EF_ELIDABLE_OR_MEMORYERROR))
    elidable3calldescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([valuedescr], [], [], [valuedescr], [], [],
                   EffectInfo.EF_ELIDABLE_CAN_RAISE))
    nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                    EffectInfo([], [], [], [], [], []))
    writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                  EffectInfo([], [], [], [adescr], [], []))
    writearraydescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [], [], [adescr], [arraydescr], []))
    writevalue3descr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [], [], [valuedescr3], [], []))
    readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                 EffectInfo([adescr], [], [], [], [], []))
    mayforcevirtdescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([nextdescr], [], [], [], [], [],
                   EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE,
                   can_invalidate=True))
    arraycopydescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [arraydescr], [], [], [arraydescr], [],
                   EffectInfo.EF_CANNOT_RAISE,
                   oopspecindex=EffectInfo.OS_ARRAYCOPY))

    raw_malloc_descr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [], [], [], [], [],
                   EffectInfo.EF_CAN_RAISE,
                   oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR))
    raw_free_descr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [], [], [], [], [],
                   EffectInfo.EF_CANNOT_RAISE,
                   oopspecindex=EffectInfo.OS_RAW_FREE))

    chararray = lltype.GcArray(lltype.Char)
    chararraydescr = cpu.arraydescrof(chararray)
    u2array = lltype.GcArray(rffi.USHORT)
    u2arraydescr = cpu.arraydescrof(u2array)

    nodefull = lltype.malloc(NODE2, zero=True)
    nodefull.parent.next = lltype.cast_pointer(lltype.Ptr(NODE), nodefull)
    nodefull.parent.nexttuple = tpl
    nodefulladdr = lltype.cast_opaque_ptr(llmemory.GCREF, nodefull)

    # array of structs (complex data)
    complexarray = lltype.GcArray(
        lltype.Struct(
            "complex",
            ("real", lltype.Float),
            ("imag", lltype.Float),
        ))
    complexarraydescr = cpu.arraydescrof(complexarray)
    complexrealdescr = cpu.interiorfielddescrof(complexarray, "real")
    compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag")
    complexarraycopydescr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [complexarraydescr], [], [], [complexarraydescr], [],
                   EffectInfo.EF_CANNOT_RAISE,
                   oopspecindex=EffectInfo.OS_ARRAYCOPY))

    rawarraydescr = cpu.arraydescrof(
        lltype.Array(lltype.Signed, hints={'nolength': True}))
    rawarraydescr_char = cpu.arraydescrof(
        lltype.Array(lltype.Char, hints={'nolength': True}))
    rawarraydescr_float = cpu.arraydescrof(
        lltype.Array(lltype.Float, hints={'nolength': True}))

    fc_array = lltype.GcArray(
        lltype.Struct("floatchar", ("float", lltype.Float),
                      ("char", lltype.Char)))
    fc_array_descr = cpu.arraydescrof(fc_array)
    fc_array_floatdescr = cpu.interiorfielddescrof(fc_array, "float")
    fc_array_chardescr = cpu.interiorfielddescrof(fc_array, "char")

    for _name, _os in [
        ('strconcatdescr', 'OS_STR_CONCAT'),
        ('strslicedescr', 'OS_STR_SLICE'),
        ('strequaldescr', 'OS_STR_EQUAL'),
        ('streq_slice_checknull_descr', 'OS_STREQ_SLICE_CHECKNULL'),
        ('streq_slice_nonnull_descr', 'OS_STREQ_SLICE_NONNULL'),
        ('streq_slice_char_descr', 'OS_STREQ_SLICE_CHAR'),
        ('streq_nonnull_descr', 'OS_STREQ_NONNULL'),
        ('streq_nonnull_char_descr', 'OS_STREQ_NONNULL_CHAR'),
        ('streq_checknull_char_descr', 'OS_STREQ_CHECKNULL_CHAR'),
        ('streq_lengthok_descr', 'OS_STREQ_LENGTHOK'),
    ]:
        if _name in ('strconcatdescr', 'strslicedescr'):
            _extra = EffectInfo.EF_ELIDABLE_OR_MEMORYERROR
        else:
            _extra = EffectInfo.EF_ELIDABLE_CANNOT_RAISE
        _oopspecindex = getattr(EffectInfo, _os)
        locals()[_name] = \
            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                EffectInfo([], [], [], [], [], [], _extra,
                           oopspecindex=_oopspecindex))
        #
        _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
        locals()[_name.replace('str', 'unicode')] = \
            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                EffectInfo([], [], [], [], [], [], _extra,
                           oopspecindex=_oopspecindex))

    s2u_descr = cpu.calldescrof(
        FUNC, FUNC.ARGS, FUNC.RESULT,
        EffectInfo([], [], [], [], [], [],
                   EffectInfo.EF_ELIDABLE_CAN_RAISE,
                   oopspecindex=EffectInfo.OS_STR2UNICODE))

    #

    class LoopToken(AbstractDescr):
        pass

    asmdescr = LoopToken()  # it can be whatever, it's not a descr though

    class FakeWarmRunnerDesc:
        pass

    FakeWarmRunnerDesc.cpu = cpu
    vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc)
    virtualtokendescr = vrefinfo.descr_virtual_token
    virtualforceddescr = vrefinfo.descr_forced
    FUNC = lltype.FuncType([], lltype.Void)
    ei = EffectInfo([], [], [], [], [], [],
                    EffectInfo.EF_CANNOT_RAISE,
                    can_invalidate=False,
                    oopspecindex=EffectInfo.OS_JIT_FORCE_VIRTUALIZABLE)
    clear_vable = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)

    jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable
    vref_descr = cpu.sizeof(vrefinfo.JIT_VIRTUAL_REF, jit_virtual_ref_vtable)

    FUNC = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
    ei = EffectInfo([], [], [], [], [], [],
                    EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                    can_invalidate=False,
                    oopspecindex=EffectInfo.OS_INT_PY_DIV)
    int_py_div_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)
    ei = EffectInfo([], [], [], [], [], [],
                    EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                    can_invalidate=False,
                    oopspecindex=EffectInfo.OS_INT_UDIV)
    int_udiv_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)
    ei = EffectInfo([], [], [], [], [], [],
                    EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                    can_invalidate=False,
                    oopspecindex=EffectInfo.OS_INT_PY_MOD)
    int_py_mod_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)

    FUNC = lltype.FuncType([], llmemory.GCREF)
    ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_ELIDABLE_CAN_RAISE)
    plain_r_calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)

    namespace = locals()
コード例 #3
0
ファイル: test_virtualref.py プロジェクト: yuyichao/pypy
 def finish_setup_for_interp_operations(self):
     self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
     self.cw.setup_vrefinfo(self.vrefinfo)
コード例 #4
0
ファイル: test_virtualref.py プロジェクト: yuyichao/pypy
class VRefTests(object):
    def finish_setup_for_interp_operations(self):
        self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
        self.cw.setup_vrefinfo(self.vrefinfo)

    def test_rewrite_graphs(self):
        class X:
            pass
        def fn():
            x = X()
            vref = virtual_ref(x)
            x1 = vref()                  # jit_force_virtual
            virtual_ref_finish(vref, x)
        #
        _get_jitcodes(self, self.CPUClass, fn, [])
        graph = self.all_graphs[0]
        assert graph.name == 'fn'
        self.vrefinfo.replace_force_virtual_with_call([graph])
        #
        def check_call(op, fname):
            assert op.opname == 'direct_call'
            assert op.args[0].value._obj._name == fname
        #
        ops = [op for block, op in graph.iterblockops()]
        check_call(ops[-3], 'virtual_ref')
        check_call(ops[-2], 'force_virtual_if_necessary')
        check_call(ops[-1], 'virtual_ref_finish')

    def test_make_vref_simple(self):
        class X:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        def f():
            x = X()
            exctx.topframeref = vref = virtual_ref(x)
            exctx.topframeref = vref_None
            virtual_ref_finish(vref, x)
            return 1
        #
        self.interp_operations(f, [])
        self.check_operations_history(new_with_vtable=1,     # X()
                                      virtual_ref=1,
                                      virtual_ref_finish=1)

    def test_make_vref_guard(self):
        if not isinstance(self, TestLLtype):
            py.test.skip("purely frontend test")
        #
        class FooBarError(Exception):
            pass
        class X:
            def __init__(self, n):
                self.n = n
        class ExCtx:
            _frame = None
        exctx = ExCtx()
        #
        @dont_look_inside
        def external(n):
            if exctx._frame is None:
                raise FooBarError
            if n > 100:
                return exctx.topframeref().n
            return n
        def enter(n):
            x = X(n + 10)
            exctx._frame = x
            exctx.topframeref = virtual_ref(x)
        def leave():
            vref = exctx.topframeref
            exctx.topframeref = vref_None
            virtual_ref_finish(vref, exctx._frame)
        def f(n):
            enter(n)
            n = external(n)
            # ^^^ the point is that X() and the vref should be kept alive here
            leave()
            return n
        #
        res = self.interp_operations(f, [5])
        assert res == 5
        self.check_operations_history(virtual_ref=1, guard_not_forced=1)
        #
        ops = self.metainterp.staticdata.stats.loops[0].operations
        [guard_op] = [op for op in ops
                         if op.getopnum() == rop.GUARD_NOT_FORCED]
        bxs1 = [box for box in guard_op.getfailargs()
                  if str(box._getrepr_()).endswith('.X')]
        assert len(bxs1) == 1
        bxs2 = [box for box in guard_op.getfailargs()
                  if str(box._getrepr_()).endswith('JitVirtualRef')]
        assert len(bxs2) == 1
        JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF
        FOO = lltype.GcStruct('FOO')
        foo = lltype.malloc(FOO)
        tok = lltype.cast_opaque_ptr(llmemory.GCREF, foo)
        bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = tok
        #
        # try reloading from blackhole.py's point of view
        from rpython.jit.metainterp.resume import ResumeDataDirectReader
        cpu = self.metainterp.cpu
        cpu.get_int_value = lambda df,i:guard_op.getfailargs()[i].getint()
        cpu.get_ref_value = lambda df,i:guard_op.getfailargs()[i].getref_base()
        class FakeMetaInterpSd:
            callinfocollection = None
        FakeMetaInterpSd.cpu = cpu
        resumereader = ResumeDataDirectReader(FakeMetaInterpSd(),
                                              guard_op.getdescr(),
                                              "deadframe")
        vrefinfo = self.metainterp.staticdata.virtualref_info
        lst = []
        vrefinfo.continue_tracing = lambda vref, virtual: \
                                        lst.append((vref, virtual))
        resumereader.consume_vref_and_vable(vrefinfo, None, None)
        del vrefinfo.continue_tracing
        assert len(lst) == 1
        lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF),
                               lst[0][0])  # assert correct type
        #
        # try reloading from pyjitpl's point of view
        self.metainterp.rebuild_state_after_failure(guard_op.getdescr(),
                                                    "deadframe")
        assert len(self.metainterp.framestack) == 1
        assert len(self.metainterp.virtualref_boxes) == 2
        assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value
        assert self.metainterp.virtualref_boxes[1].value == bxs2[0].value

    def test_make_vref_escape_after_finish(self):
        jitdriver = JitDriver(greens = [], reds = ['n'])
        #
        class X:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def g(vref):
            # we cannot do anything with the vref after the call to finish()
            pass
        #
        def f(n):
            while n > 0:
                jitdriver.can_enter_jit(n=n)
                jitdriver.jit_merge_point(n=n)
                x = X()
                x.n = n
                exctx.topframeref = vref = virtual_ref(x)
                # here, 'x' should be virtual
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, x)
                # 'x' and 'vref' can randomly escape after the call to
                # finish().
                g(vref)
                n -= 1
            return 1
        #
        self.meta_interp(f, [10])
        self.check_resops(new_with_vtable=2) # the vref
        self.check_aborted_count(0)

    def test_simple_all_removed(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
        #
        self.meta_interp(f, [15])
        self.check_resops(new_with_vtable=0, new_array=0)
        self.check_aborted_count(0)

    def test_simple_no_access(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            if n > 1000:
                return compute_unique_id(exctx.topframeref())
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
        #
        self.meta_interp(f, [15])
        self.check_resops(new_with_vtable=2,     # the vref: xy doesn't need to be forced
                         new_array=0)           # and neither xy.next1/2/3
        self.check_aborted_count(0)

    def test_simple_force_always(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            m = exctx.topframeref().n
            assert m == n
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
                exctx.topframeref = vref_None
        #
        self.meta_interp(f, [15])
        self.check_resops(new_with_vtable=4,   # XY(), the vref
                          new_array=6)         # next1/2/3
        self.check_aborted_count(0)

    def test_simple_force_sometimes(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            if n == 13:
                exctx.m = exctx.topframeref().n
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
                buf[0] = chr(n)
                # this is a raw virtual
                xy.next4 = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                lltype.free(xy.next4, flavor='raw')
                xy.next4 = lltype.nullptr(rffi.CCHARP.TO)
                virtual_ref_finish(vref, xy)
                exctx.topframeref = vref_None
                lltype.free(buf, flavor='raw')
            return exctx.m
        #
        res = self.meta_interp(f, [30])
        assert res == 13
        self.check_resops(new_with_vtable=2,   # the vref, but not XY()
                          new_array=0)         # and neither next1/2/3
        self.check_trace_count(1)
        self.check_aborted_count(0)

    def test_blackhole_forces(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            exctx.m = exctx.topframeref().n
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if n == 13:
                    externalfn(n)
                n -= 1
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
            return exctx.m
        #
        res = self.meta_interp(f, [30])
        assert res == 13
        self.check_resops(new_with_vtable=0, # all virtualized in the n!=13 loop
                         new_array=0)
        self.check_trace_count(1)
        self.check_aborted_count(0)

    def test_bridge_forces(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        A = lltype.GcArray(lltype.Signed)
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            exctx.m = exctx.topframeref().n
            return 1
        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.next4 = lltype.malloc(A, 0)
                xy.next5 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if n % 6 == 0:
                    xy.next1 = lltype.nullptr(A)
                    xy.next2 = lltype.nullptr(A)
                    xy.next3 = lltype.nullptr(A)
                    externalfn(n)
                n -= 1
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                xy.next4 = lltype.nullptr(A)
                xy.next5 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
            return exctx.m
        #
        res = self.meta_interp(f, [72])
        assert res == 6
        self.check_trace_count(2)     # the loop and the bridge
        self.check_resops(new_with_vtable=2,  # loop: nothing; bridge: vref, xy
                         new_array=2)        # bridge: next4, next5
        self.check_aborted_count(0)

    def test_jit_force_virtual_seen(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])

        A = lltype.GcArray(lltype.Signed)

        class XY(object):
            pass

        class ExCtx(object):
            pass
        exctx = ExCtx()
        escapes = []

        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                escapes.append(xy)
                xy.next1 = lltype.malloc(A, 0)
                n = exctx.topframeref().n - 1
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return 1
        #
        res = self.meta_interp(f, [15])
        assert res == 1
        self.check_resops(new_with_vtable=2,     # xy
                          new_array=2)           # next1
        self.check_aborted_count(0)

    def test_recursive_call_1(self):
        myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame'])
        #
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        def f(frame, n, reclevel):
            while n > 0:
                myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
                myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
                if reclevel == 0:
                    return n
                xy = XY()
                exctx.topframeref = vref = virtual_ref(xy)
                m = f(xy, n, reclevel-1)
                assert m == n
                n -= 1
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return 2
        def main(n, reclevel):
            return f(XY(), n, reclevel)
        #
        res = self.meta_interp(main, [15, 1])
        assert res == main(15, 1)
        self.check_aborted_count(0)

    def test_recursive_call_2(self):
        myjitdriver = JitDriver(greens = [], reds = ['n', 'rec', 'frame'])
        #
        class XY:
            n = 0
        class ExCtx:
            pass
        exctx = ExCtx()
        #
        def f(frame, n, reclevel):
            while n > 0:
                myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
                myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
                frame.n += 1
                xy = XY()
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if reclevel > 0:
                    m = f(xy, frame.n, reclevel-1)
                    assert xy.n == m
                    n -= 1
                else:
                    n -= 2
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return frame.n
        def main(n, reclevel):
            return f(XY(), n, reclevel)
        #
        res = self.meta_interp(main, [10, 2])
        assert res == main(10, 2)
        self.check_aborted_count(0)

    def test_alloc_virtualref_and_then_alloc_structure(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        class XY:
            pass
        class ExCtx:
            pass
        exctx = ExCtx()
        @dont_look_inside
        def escapexy(xy):
            print 'escapexy:', xy.n
            if xy.n % 5 == 0:
                vr = exctx.vr
                print 'accessing via vr:', vr()
                assert vr() is xy
        #
        def f(n):
            while n > 0:
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                vr = virtual_ref(xy)
                # force the virtualref to be allocated
                exctx.vr = vr
                # force xy to be allocated
                escapexy(xy)
                # clean up
                exctx.vr = vref_None
                virtual_ref_finish(vr, xy)
                n -= 1
            return 1
        #
        res = self.meta_interp(f, [15])
        assert res == 1
        self.check_resops(new_with_vtable=4)     # vref, xy

    def test_cannot_use_invalid_virtualref(self):
        myjitdriver = JitDriver(greens = [], reds = ['n'])
        #
        class XY:
            n = 0
        #
        def fn(n):
            res = False
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                vref = virtual_ref(xy)
                virtual_ref_finish(vref, xy)
                vref() # raises InvalidVirtualRef when jitted
                n -= 1
            return res
        #
        py.test.raises(InvalidVirtualRef, "fn(10)")
        py.test.raises(UnknownException, "self.meta_interp(fn, [10])")

    def test_call_virtualref_already_forced(self):
        myjitdriver = JitDriver(greens = [], reds = ['n', 'res'])
        #
        class XY:
            n = 0
        #
        @dont_look_inside
        def force_it(vref, n):
            if n % 6 == 0:
                return vref().n
            return 0
        def fn(n):
            res = 0
            while n > 0:
                myjitdriver.can_enter_jit(n=n, res=res)
                myjitdriver.jit_merge_point(n=n, res=res)
                xy = XY()
                xy.n = n
                vref = virtual_ref(xy)
                force_it(vref, n)
                virtual_ref_finish(vref, xy)
                res += force_it(vref, n) # doesn't raise, because it was already forced
                n -= 1
            return res
        #
        assert fn(10) == 6
        res = self.meta_interp(fn, [10])
        assert res == 6

    def test_is_virtual(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
        class X:
            pass
        @dont_look_inside
        def residual(vref):
            return vref.virtual
        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                x = X()
                vref = virtual_ref(x)
                res1 = residual(vref)
                virtual_ref_finish(vref, x)
                n -= 1
            return res1
        #
        res = self.meta_interp(f, [10])
        assert res == 1

    def test_is_not_virtual_none(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
        @dont_look_inside
        def residual(vref):
            return vref.virtual
        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                res1 = residual(vref_None)
                n -= 1
            return res1
        #
        res = self.meta_interp(f, [10])
        assert res == 0

    def test_is_not_virtual_non_none(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])
        class X:
            pass
        @dont_look_inside
        def residual(vref):
            return vref.virtual
        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                x = X()
                res1 = residual(non_virtual_ref(x))
                n -= 1
            return res1
        #
        res = self.meta_interp(f, [10])
        assert res == 0

    def test_force_virtual_vref(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'ec'])

        class ExecutionContext(object):
            pass

        class Frame(object):
            def __init__(self, x):
                self.x = x

        def f(n):
            ec = ExecutionContext()
            while n > 0:
                myjitdriver.jit_merge_point(n=n, ec=ec)
                frame = Frame(1)
                ec.topframeref = virtual_ref(frame)
                n -= ec.topframeref().x
                frame_vref = ec.topframeref
                ec.topframeref = vref_None
                virtual_ref_finish(frame_vref, frame)
            return n
        res = self.meta_interp(f, [10])
        assert res == 0
        self.check_resops({
            'int_sub': 2, 'int_gt': 2, 'jump': 1, 'guard_true': 2,
            'force_token': 2, 'setfield_gc': 1
        })
コード例 #5
0
ファイル: test_virtualref.py プロジェクト: sota/pypy-old
 def finish_setup_for_interp_operations(self):
     self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
     self.cw.setup_vrefinfo(self.vrefinfo)
コード例 #6
0
ファイル: test_virtualref.py プロジェクト: sota/pypy-old
class VRefTests(object):
    def finish_setup_for_interp_operations(self):
        self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
        self.cw.setup_vrefinfo(self.vrefinfo)

    def test_rewrite_graphs(self):
        class X:
            pass

        def fn():
            x = X()
            vref = virtual_ref(x)
            x1 = vref()  # jit_force_virtual
            virtual_ref_finish(vref, x)

        #
        _get_jitcodes(self, self.CPUClass, fn, [])
        graph = self.all_graphs[0]
        assert graph.name == 'fn'
        self.vrefinfo.replace_force_virtual_with_call([graph])

        #
        def check_call(op, fname):
            assert op.opname == 'direct_call'
            assert op.args[0].value._obj._name.startswith(fname)

        #
        ops = [op for block, op in graph.iterblockops()]
        check_call(ops[-3], 'virtual_ref')
        check_call(ops[-2], 'force_virtual_if_necessary')
        check_call(ops[-1], 'virtual_ref_finish')

    def test_make_vref_simple(self):
        class X:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()

        #
        def f():
            x = X()
            exctx.topframeref = vref = virtual_ref(x)
            exctx.topframeref = vref_None
            virtual_ref_finish(vref, x)
            return 1

        #
        self.interp_operations(f, [])
        self.check_operations_history(
            new_with_vtable=1,  # X()
            virtual_ref=1,
            virtual_ref_finish=1)

    def test_make_vref_guard(self):
        if not isinstance(self, TestLLtype):
            py.test.skip("purely frontend test")
        #
        class FooBarError(Exception):
            pass

        class X:
            def __init__(self, n):
                self.n = n

        class ExCtx:
            _frame = None

        exctx = ExCtx()
        #
        @dont_look_inside
        def external(n):
            if exctx._frame is None:
                raise FooBarError
            if n > 100:
                return exctx.topframeref().n
            return n

        def enter(n):
            x = X(n + 10)
            exctx._frame = x
            exctx.topframeref = virtual_ref(x)

        def leave():
            vref = exctx.topframeref
            exctx.topframeref = vref_None
            virtual_ref_finish(vref, exctx._frame)

        def f(n):
            enter(n)
            n = external(n)
            # ^^^ the point is that X() and the vref should be kept alive here
            leave()
            return n

        #
        res = self.interp_operations(f, [5])
        assert res == 5
        self.check_operations_history(virtual_ref=1, guard_not_forced=1)
        #
        ops = self.metainterp.staticdata.stats.loops[0].operations
        [guard_op
         ] = [op for op in ops if op.getopnum() == rop.GUARD_NOT_FORCED]
        bxs1 = [box for box in guard_op.getfailargs() if '.X' in str(box)]
        assert len(bxs1) == 1
        bxs2 = [(i, box) for i, box in enumerate(guard_op.getfailargs())
                if 'JitVirtualRef' in str(box)]
        assert len(bxs2) == 1
        JIT_VIRTUAL_REF = self.vrefinfo.JIT_VIRTUAL_REF
        FOO = lltype.GcStruct('FOO')
        foo = lltype.malloc(FOO)
        tok = lltype.cast_opaque_ptr(llmemory.GCREF, foo)
        cpu = self.metainterp.cpu
        py.test.skip("rewrite this test")
        bxs2[0].getref(lltype.Ptr(JIT_VIRTUAL_REF)).virtual_token = tok
        #
        # try reloading from blackhole.py's point of view
        from rpython.jit.metainterp.resume import ResumeDataDirectReader
        cpu.get_int_value = lambda df, i: guard_op.getfailargs()[i].getint()
        cpu.get_ref_value = lambda df, i: guard_op.getfailargs()[
            i].getref_base()

        class FakeMetaInterpSd:
            callinfocollection = None

        FakeMetaInterpSd.cpu = cpu
        resumereader = ResumeDataDirectReader(FakeMetaInterpSd(),
                                              guard_op.getdescr(), "deadframe")
        vrefinfo = self.metainterp.staticdata.virtualref_info
        lst = []
        vrefinfo.continue_tracing = lambda vref, virtual: \
                                        lst.append((vref, virtual))
        resumereader.consume_vref_and_vable(vrefinfo, None, None)
        del vrefinfo.continue_tracing
        assert len(lst) == 1
        lltype.cast_opaque_ptr(lltype.Ptr(JIT_VIRTUAL_REF),
                               lst[0][0])  # assert correct type
        #
        # try reloading from pyjitpl's point of view
        self.metainterp.rebuild_state_after_failure(guard_op.getdescr(),
                                                    "deadframe")
        assert len(self.metainterp.framestack) == 1
        assert len(self.metainterp.virtualref_boxes) == 2
        assert self.metainterp.virtualref_boxes[0].value == bxs1[0].value
        assert self.metainterp.virtualref_boxes[1].value == bxs2[0].value

    def test_make_vref_escape_after_finish(self):
        jitdriver = JitDriver(greens=[], reds=['n'])

        #
        class X:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def g(vref):
            # we cannot do anything with the vref after the call to finish()
            pass

        #
        def f(n):
            while n > 0:
                jitdriver.can_enter_jit(n=n)
                jitdriver.jit_merge_point(n=n)
                x = X()
                x.n = n
                exctx.topframeref = vref = virtual_ref(x)
                # here, 'x' should be virtual
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, x)
                # 'x' and 'vref' can randomly escape after the call to
                # finish().
                g(vref)
                n -= 1
            return 1

        #
        self.meta_interp(f, [10])
        self.check_resops(new_with_vtable=2)  # the vref
        self.check_aborted_count(0)

    def test_simple_all_removed(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)

        #
        self.meta_interp(f, [15])
        self.check_resops(new_with_vtable=0, new_array=0)
        self.check_aborted_count(0)

    def test_simple_no_access(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            if n > 1000:
                return compute_unique_id(exctx.topframeref())
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)

        #
        self.meta_interp(f, [15])
        self.check_resops(
            new_with_vtable=2,  # the vref: xy doesn't need to be forced
            new_array=0)  # and neither xy.next1/2/3
        self.check_aborted_count(0)

    def test_simple_force_always(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            m = exctx.topframeref().n
            assert m == n
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
                exctx.topframeref = vref_None

        #
        self.meta_interp(f, [15])
        self.check_resops(
            new_with_vtable=4,  # XY(), the vref
            new_array=6)  # next1/2/3
        self.check_aborted_count(0)

    def test_simple_force_sometimes(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            if n == 13:
                exctx.m = exctx.topframeref().n
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
                buf[0] = chr(n)
                # this is a raw virtual
                xy.next4 = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw')
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                n -= externalfn(n)
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                lltype.free(xy.next4, flavor='raw')
                xy.next4 = lltype.nullptr(rffi.CCHARP.TO)
                virtual_ref_finish(vref, xy)
                exctx.topframeref = vref_None
                lltype.free(buf, flavor='raw')
            return exctx.m

        #
        res = self.meta_interp(f, [30])
        assert res == 13
        self.check_resops(
            new_with_vtable=2,  # the vref, but not XY()
            new_array=0)  # and neither next1/2/3
        self.check_trace_count(1)
        self.check_aborted_count(0)

    def test_blackhole_forces(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            exctx.m = exctx.topframeref().n
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if n == 13:
                    externalfn(n)
                n -= 1
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
            return exctx.m

        #
        res = self.meta_interp(f, [30])
        assert res == 13
        self.check_resops(
            new_with_vtable=0,  # all virtualized in the n!=13 loop
            new_array=0)
        self.check_trace_count(1)
        self.check_aborted_count(0)

    def test_bridge_forces(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])
        #
        A = lltype.GcArray(lltype.Signed)

        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()
        #
        @dont_look_inside
        def externalfn(n):
            exctx.m = exctx.topframeref().n
            return 1

        #
        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.next1 = lltype.malloc(A, 0)
                xy.next2 = lltype.malloc(A, 0)
                xy.next3 = lltype.malloc(A, 0)
                xy.next4 = lltype.malloc(A, 0)
                xy.next5 = lltype.malloc(A, 0)
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if n % 6 == 0:
                    xy.next1 = lltype.nullptr(A)
                    xy.next2 = lltype.nullptr(A)
                    xy.next3 = lltype.nullptr(A)
                    externalfn(n)
                n -= 1
                exctx.topframeref = vref_None
                xy.next1 = lltype.nullptr(A)
                xy.next2 = lltype.nullptr(A)
                xy.next3 = lltype.nullptr(A)
                xy.next4 = lltype.nullptr(A)
                xy.next5 = lltype.nullptr(A)
                virtual_ref_finish(vref, xy)
            return exctx.m

        #
        res = self.meta_interp(f, [72])
        assert res == 6
        self.check_trace_count(2)  # the loop and the bridge
        self.check_resops(
            new_with_vtable=2,  # loop: nothing; bridge: vref, xy
            new_array=2)  # bridge: next4, next5
        self.check_aborted_count(0)

    def test_jit_force_virtual_seen(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])

        A = lltype.GcArray(lltype.Signed)

        class XY(object):
            pass

        class ExCtx(object):
            pass

        exctx = ExCtx()
        escapes = []

        def f(n):
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                escapes.append(xy)
                xy.next1 = lltype.malloc(A, 0)
                n = exctx.topframeref().n - 1
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return 1

        #
        res = self.meta_interp(f, [15])
        assert res == 1
        self.check_resops(
            new_with_vtable=2,  # xy
            new_array=2)  # next1
        self.check_aborted_count(0)

    def test_recursive_call_1(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'rec', 'frame'])

        #
        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()

        #
        def f(frame, n, reclevel):
            while n > 0:
                myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
                myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
                if reclevel == 0:
                    return n
                xy = XY()
                exctx.topframeref = vref = virtual_ref(xy)
                m = f(xy, n, reclevel - 1)
                assert m == n
                n -= 1
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return 2

        def main(n, reclevel):
            return f(XY(), n, reclevel)

        #
        res = self.meta_interp(main, [15, 1])
        assert res == main(15, 1)
        self.check_aborted_count(0)

    def test_recursive_call_2(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'rec', 'frame'])

        #
        class XY:
            n = 0

        class ExCtx:
            pass

        exctx = ExCtx()

        #
        def f(frame, n, reclevel):
            while n > 0:
                myjitdriver.can_enter_jit(n=n, frame=frame, rec=reclevel)
                myjitdriver.jit_merge_point(n=n, frame=frame, rec=reclevel)
                frame.n += 1
                xy = XY()
                xy.n = n
                exctx.topframeref = vref = virtual_ref(xy)
                if reclevel > 0:
                    m = f(xy, frame.n, reclevel - 1)
                    assert xy.n == m
                    n -= 1
                else:
                    n -= 2
                exctx.topframeref = vref_None
                virtual_ref_finish(vref, xy)
            return frame.n

        def main(n, reclevel):
            return f(XY(), n, reclevel)

        #
        res = self.meta_interp(main, [10, 2])
        assert res == main(10, 2)
        self.check_aborted_count(0)

    def test_alloc_virtualref_and_then_alloc_structure(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])

        #
        class XY:
            pass

        class ExCtx:
            pass

        exctx = ExCtx()

        @dont_look_inside
        def escapexy(xy):
            print 'escapexy:', xy.n
            if xy.n % 5 == 0:
                vr = exctx.vr
                print 'accessing via vr:', vr()
                assert vr() is xy

        #
        def f(n):
            while n > 0:
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                vr = virtual_ref(xy)
                # force the virtualref to be allocated
                exctx.vr = vr
                # force xy to be allocated
                escapexy(xy)
                # clean up
                exctx.vr = vref_None
                virtual_ref_finish(vr, xy)
                n -= 1
            return 1

        #
        res = self.meta_interp(f, [15])
        assert res == 1
        self.check_resops(new_with_vtable=4)  # vref, xy

    def test_cannot_use_invalid_virtualref(self):
        myjitdriver = JitDriver(greens=[], reds=['n'])

        #
        class XY:
            n = 0

        #
        def fn(n):
            res = False
            while n > 0:
                myjitdriver.can_enter_jit(n=n)
                myjitdriver.jit_merge_point(n=n)
                xy = XY()
                xy.n = n
                vref = virtual_ref(xy)
                virtual_ref_finish(vref, xy)
                vref()  # raises InvalidVirtualRef when jitted
                n -= 1
            return res

        #
        py.test.raises(UnknownException, "self.meta_interp(fn, [10])")

    def test_call_virtualref_already_forced(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res'])

        #
        class XY:
            n = 0

        #
        @dont_look_inside
        def force_it(vref, n):
            if n % 6 == 0:
                return vref().n
            return 0

        def fn(n):
            res = 0
            while n > 0:
                myjitdriver.can_enter_jit(n=n, res=res)
                myjitdriver.jit_merge_point(n=n, res=res)
                xy = XY()
                xy.n = n
                vref = virtual_ref(xy)
                force_it(vref, n)
                virtual_ref_finish(vref, xy)
                res += force_it(
                    vref, n)  # doesn't raise, because it was already forced
                n -= 1
            return res

        #
        assert fn(10) == 6
        res = self.meta_interp(fn, [10])
        assert res == 6

    def test_is_virtual(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])

        class X:
            pass

        @dont_look_inside
        def residual(vref):
            return vref.virtual

        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                x = X()
                vref = virtual_ref(x)
                res1 = residual(vref)
                virtual_ref_finish(vref, x)
                n -= 1
            return res1

        #
        res = self.meta_interp(f, [10])
        assert res == 1

    def test_is_not_virtual_none(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])

        @dont_look_inside
        def residual(vref):
            return vref.virtual

        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                res1 = residual(vref_None)
                n -= 1
            return res1

        #
        res = self.meta_interp(f, [10])
        assert res == 0

    def test_is_not_virtual_non_none(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'res1'])

        class X:
            pass

        @dont_look_inside
        def residual(vref):
            return vref.virtual

        #
        def f(n):
            res1 = -42
            while n > 0:
                myjitdriver.jit_merge_point(n=n, res1=res1)
                x = X()
                res1 = residual(non_virtual_ref(x))
                n -= 1
            return res1

        #
        res = self.meta_interp(f, [10])
        assert res == 0

    def test_force_virtual_vref(self):
        myjitdriver = JitDriver(greens=[], reds=['n', 'ec'])

        class ExecutionContext(object):
            pass

        class Frame(object):
            def __init__(self, x):
                self.x = x

        def f(n):
            ec = ExecutionContext()
            while n > 0:
                myjitdriver.jit_merge_point(n=n, ec=ec)
                frame = Frame(1)
                ec.topframeref = virtual_ref(frame)
                n -= ec.topframeref().x
                frame_vref = ec.topframeref
                ec.topframeref = vref_None
                virtual_ref_finish(frame_vref, frame)
            return n

        res = self.meta_interp(f, [10])
        assert res == 0
        self.check_resops({
            'int_sub': 2,
            'int_gt': 2,
            'jump': 1,
            'guard_true': 2,
            'force_token': 2,
            'setfield_gc': 1
        })

    def test_vref_like_pypy(self):
        myjitdriver = JitDriver(greens=['n'], reds=['i', 'ec', 'frame'])

        class ExecutionContext(object):
            topframeref = vref_None

            def enter(self, frame):
                frame.f_backref = self.topframeref
                self.topframeref = virtual_ref(frame)

            def leave(self, frame):
                frame_vref = self.topframeref
                self.topframeref = frame.f_backref
                frame.f_backref()
                virtual_ref_finish(frame_vref, frame)

        class PyFrame(object):
            pass

        def dispatch(ec, frame, n):
            i = 0
            while True:
                myjitdriver.jit_merge_point(n=n, ec=ec, frame=frame, i=i)
                i += 1
                if n == 1:
                    execute_frame(ec, 2)
                    if i >= 10:
                        break
                elif n == 2:
                    execute_frame(ec, 3)
                    if i == 2:
                        break
                elif n == 3:
                    break

        def execute_frame(ec, n):
            frame = PyFrame()
            ec.enter(frame)
            dispatch(ec, frame, n)
            ec.leave(frame)
            return n

        def entry_point():
            return execute_frame(ExecutionContext(), 1)

        assert entry_point() == 1
        r = self.meta_interp(entry_point, [], inline=True)
        assert r == 1
コード例 #7
0
ファイル: test_util.py プロジェクト: weijiwei/pypy
class LLtypeMixin(object):
    type_system = 'lltype'

    def get_class_of_box(self, box):
        return box.getref(rclass.OBJECTPTR).typeptr

    node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    node_vtable.name = rclass.alloc_array_name('node')
    node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable)
    node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True)
    node_vtable2.name = rclass.alloc_array_name('node2')
    node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2)
    cpu = runner.LLGraphCPU(None)

    NODE = lltype.GcForwardReference()
    NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT),
                                        ('value', lltype.Signed),
                                        ('floatval', lltype.Float),
                                        ('charval', lltype.Char),
                                        ('next', lltype.Ptr(NODE))))
    NODE2 = lltype.GcStruct('NODE2', ('parent', NODE),
                                     ('other', lltype.Ptr(NODE)))
    node = lltype.malloc(NODE)
    node.parent.typeptr = node_vtable
    node2 = lltype.malloc(NODE2)
    node2.parent.parent.typeptr = node_vtable2
    nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
    myptr = nodebox.value
    myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(NODE))
    nullptr = lltype.nullptr(llmemory.GCREF.TO)
    nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node2))
    nodesize = cpu.sizeof(NODE)
    nodesize2 = cpu.sizeof(NODE2)
    valuedescr = cpu.fielddescrof(NODE, 'value')
    floatdescr = cpu.fielddescrof(NODE, 'floatval')
    chardescr = cpu.fielddescrof(NODE, 'charval')
    nextdescr = cpu.fielddescrof(NODE, 'next')
    otherdescr = cpu.fielddescrof(NODE2, 'other')

    accessor = FieldListAccessor()
    accessor.initialize(None, {'inst_field': IR_QUASIIMMUTABLE})
    QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
                            ('mutate_field', rclass.OBJECTPTR),
                            hints={'immutable_fields': accessor})
    quasisize = cpu.sizeof(QUASI)
    quasi = lltype.malloc(QUASI, immortal=True)
    quasi.inst_field = -4247
    quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
    quasibox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, quasi))
    quasiptr = quasibox.value
    quasiimmutdescr = QuasiImmutDescr(cpu, quasibox,
                                      quasifielddescr,
                                      cpu.fielddescrof(QUASI, 'mutate_field'))

    NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT),
                                         ('ref', lltype.Ptr(OBJECT)))
    nodeobj = lltype.malloc(NODEOBJ)
    nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
    refdescr = cpu.fielddescrof(NODEOBJ, 'ref')

    INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT),
                                                ('intval', lltype.Signed))
    INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT),
                                            ('intval', lltype.Signed),
                                            hints={'immutable': True})
    intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
    immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')

    PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT),
                                            ('ptrval', lltype.Ptr(OBJECT)),
                                            hints={'immutable': True})
    ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval')

    arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
    floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))

    # a GcStruct not inheriting from OBJECT
    S = lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('b', lltype.Ptr(NODE)))
    ssize = cpu.sizeof(S)
    adescr = cpu.fielddescrof(S, 'a')
    bdescr = cpu.fielddescrof(S, 'b')
    sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)))
    arraydescr2 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(S)))

    T = lltype.GcStruct('TUPLE',
                        ('c', lltype.Signed),
                        ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
    tsize = cpu.sizeof(T)
    cdescr = cpu.fielddescrof(T, 'c')
    ddescr = cpu.fielddescrof(T, 'd')
    arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE)))

    U = lltype.GcStruct('U',
                        ('parent', OBJECT),
                        ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
    u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
    u_vtable_adr = llmemory.cast_ptr_to_adr(u_vtable)
    usize = cpu.sizeof(U)
    onedescr = cpu.fielddescrof(U, 'one')

    FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
    plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                     EffectInfo.MOST_GENERAL)
    nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                    EffectInfo([], [], [], [], [], []))
    writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                  EffectInfo([], [], [], [adescr], [], []))
    writearraydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                  EffectInfo([], [], [], [adescr], [arraydescr],
                                             []))
    readadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                 EffectInfo([adescr], [], [], [], [], []))
    mayforcevirtdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                 EffectInfo([nextdescr], [], [], [], [], [],
                            EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE,
                            can_invalidate=True))
    arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
             EffectInfo([], [arraydescr], [], [], [arraydescr], [],
                        EffectInfo.EF_CANNOT_RAISE,
                        oopspecindex=EffectInfo.OS_ARRAYCOPY))

    raw_malloc_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
             EffectInfo([], [], [], [], [], [],
                        EffectInfo.EF_CAN_RAISE,
                        oopspecindex=EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR))
    raw_free_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
             EffectInfo([], [], [], [], [], [],
                        EffectInfo.EF_CANNOT_RAISE,
                        oopspecindex=EffectInfo.OS_RAW_FREE))

    chararray = lltype.GcArray(lltype.Char)
    chararraydescr = cpu.arraydescrof(chararray)
    u2array = lltype.GcArray(rffi.USHORT)
    u2arraydescr = cpu.arraydescrof(u2array)

    # array of structs (complex data)
    complexarray = lltype.GcArray(
        lltype.Struct("complex",
            ("real", lltype.Float),
            ("imag", lltype.Float),
        )
    )
    complexarraydescr = cpu.arraydescrof(complexarray)
    complexrealdescr = cpu.interiorfielddescrof(complexarray, "real")
    compleximagdescr = cpu.interiorfielddescrof(complexarray, "imag")
    complexarraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
            EffectInfo([], [complexarraydescr], [], [], [complexarraydescr], [],
                       EffectInfo.EF_CANNOT_RAISE,
                       oopspecindex=EffectInfo.OS_ARRAYCOPY))

    rawarraydescr = cpu.arraydescrof(lltype.Array(lltype.Signed,
                                                  hints={'nolength': True}))
    rawarraydescr_char = cpu.arraydescrof(lltype.Array(lltype.Char,
                                                       hints={'nolength': True}))
    rawarraydescr_float = cpu.arraydescrof(lltype.Array(lltype.Float,
                                                        hints={'nolength': True}))

    fc_array = lltype.GcArray(
        lltype.Struct(
            "floatchar", ("float", lltype.Float), ("char", lltype.Char)))
    fc_array_descr = cpu.arraydescrof(fc_array)
    fc_array_floatdescr = cpu.interiorfielddescrof(fc_array, "float")
    fc_array_chardescr = cpu.interiorfielddescrof(fc_array, "char")

    for _name, _os in [
        ('strconcatdescr',               'OS_STR_CONCAT'),
        ('strslicedescr',                'OS_STR_SLICE'),
        ('strequaldescr',                'OS_STR_EQUAL'),
        ('streq_slice_checknull_descr',  'OS_STREQ_SLICE_CHECKNULL'),
        ('streq_slice_nonnull_descr',    'OS_STREQ_SLICE_NONNULL'),
        ('streq_slice_char_descr',       'OS_STREQ_SLICE_CHAR'),
        ('streq_nonnull_descr',          'OS_STREQ_NONNULL'),
        ('streq_nonnull_char_descr',     'OS_STREQ_NONNULL_CHAR'),
        ('streq_checknull_char_descr',   'OS_STREQ_CHECKNULL_CHAR'),
        ('streq_lengthok_descr',         'OS_STREQ_LENGTHOK'),
        ]:
        _oopspecindex = getattr(EffectInfo, _os)
        locals()[_name] = \
            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE,
                           oopspecindex=_oopspecindex))
        #
        _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
        locals()[_name.replace('str', 'unicode')] = \
            cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE,
                           oopspecindex=_oopspecindex))

    s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
            EffectInfo([], [], [], [], [], [],
                       oopspecindex=EffectInfo.OS_STR2UNICODE))
    #

    class LoopToken(AbstractDescr):
        pass
    asmdescr = LoopToken() # it can be whatever, it's not a descr though

    from rpython.jit.metainterp.virtualref import VirtualRefInfo

    class FakeWarmRunnerDesc:
        pass
    FakeWarmRunnerDesc.cpu = cpu
    vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc)
    virtualtokendescr = vrefinfo.descr_virtual_token
    virtualforceddescr = vrefinfo.descr_forced
    FUNC = lltype.FuncType([], lltype.Void)
    ei = EffectInfo([], [], [], [], [], [], EffectInfo.EF_CANNOT_RAISE,
                    can_invalidate=False,
                    oopspecindex=EffectInfo.OS_JIT_FORCE_VIRTUALIZABLE)
    clear_vable = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, ei)

    jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable
    jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable)

    register_known_gctype(cpu, node_vtable,  NODE)
    register_known_gctype(cpu, node_vtable2, NODE2)
    register_known_gctype(cpu, u_vtable,     U)
    register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
    register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT)
    register_known_gctype(cpu, intobj_immut_vtable,   INTOBJ_IMMUT)
    register_known_gctype(cpu, ptrobj_immut_vtable,   PTROBJ_IMMUT)

    namespace = locals()