Exemple #1
0
 def __init__(self,
              rtyper,
              key_repr,
              value_repr,
              dictkey,
              dictvalue,
              custom_eq_hash=None,
              force_non_null=False):
     self.rtyper = rtyper
     self.DICT = lltype.GcForwardReference()
     self.lowleveltype = lltype.Ptr(self.DICT)
     self.custom_eq_hash = custom_eq_hash is not None
     if not isinstance(key_repr,
                       rmodel.Repr):  # not computed yet, done by setup()
         assert callable(key_repr)
         self._key_repr_computer = key_repr
     else:
         self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr)
     if not isinstance(value_repr,
                       rmodel.Repr):  # not computed yet, done by setup()
         assert callable(value_repr)
         self._value_repr_computer = value_repr
     else:
         self.external_value_repr, self.value_repr = self.pickrepr(
             value_repr)
     self.dictkey = dictkey
     self.dictvalue = dictvalue
     self.dict_cache = {}
     self._custom_eq_hash_repr = custom_eq_hash
     self.force_non_null = force_non_null
Exemple #2
0
def test_size_descr_stack_overflow_bug():
    c0 = GcCache(False)
    S = lltype.GcForwardReference()
    P = lltype.Ptr(S)
    fields = [('x%d' % i, P) for i in range(1500)]
    S.become(lltype.GcStruct('S', *fields))
    get_size_descr(c0, S)
Exemple #3
0
 def test_malloc_struct_of_ptr_struct(self):
     S3 = lltype.GcForwardReference()
     S3.become(
         lltype.GcStruct('S3', ('gcptr_struct', S), ('prev', lltype.Ptr(S)),
                         ('next', lltype.Ptr(S))))
     s3 = self.malloc(S3)
     assert s3.gcptr_struct.prev == lltype.nullptr(S)
     assert s3.gcptr_struct.next == lltype.nullptr(S)
Exemple #4
0
 def setup_method(self, meth):
     cpu = CPU(None, None)
     cpu.gc_ll_descr = GCDescrShadowstackDirect()
     wbd = cpu.gc_ll_descr.write_barrier_descr
     wbd.jit_wb_if_flag_byteofs = 0  # directly into 'hdr' field
     S = lltype.GcForwardReference()
     S.become(
         lltype.GcStruct('S', ('hdr', lltype.Signed), ('x', lltype.Ptr(S))))
     cpu.gc_ll_descr.fielddescr_tid = cpu.fielddescrof(S, 'hdr')
     self.S = S
     self.cpu = cpu
Exemple #5
0
def test_recursive_structure():
    F = lltype.GcForwardReference()
    S = lltype.GcStruct('abc', ('x', lltype.Ptr(F)))
    F.become(S)

    def f():
        s1 = lltype.malloc(S)
        s2 = lltype.malloc(S)
        s1.x = s2

    t, transformer = rtype_and_transform(f, [],
                                         RefcountingGCTransformer,
                                         check=False)
Exemple #6
0
def get_shadowstackref(root_walker, gctransformer):
    if hasattr(gctransformer, '_SHADOWSTACKREF'):
        return gctransformer._SHADOWSTACKREF

    SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference())
    SHADOWSTACKREF = lltype.GcStruct(
        'ShadowStackRef',
        ('base', llmemory.Address),
        ('top', llmemory.Address),
        ('context', llmemory.Address),
        #('fullstack', lltype.Bool),
        rtti=True)
    SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF)

    def customtrace(gc, obj, callback, arg):
        obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
        addr = obj.top
        start = obj.base
        while addr != start:
            addr -= sizeofaddr
            gc._trace_callback(callback, arg, addr)

    gc = gctransformer.gcdata.gc
    assert not hasattr(gc, 'custom_trace_dispatcher')
    # ^^^ create_custom_trace_funcs() must not run before this
    gctransformer.translator.rtyper.custom_trace_funcs.append(
        (SHADOWSTACKREF, customtrace))

    def shadowstack_destructor(shadowstackref):
        if root_walker.stacklet_support:
            from rpython.rlib import _rffi_stacklet as _c
            h = shadowstackref.context
            h = llmemory.cast_adr_to_ptr(h, _c.handle)
            shadowstackref.context = llmemory.NULL
        #
        base = shadowstackref.base
        shadowstackref.base = llmemory.NULL
        shadowstackref.top = llmemory.NULL
        llmemory.raw_free(base)
        #
        if root_walker.stacklet_support:
            if h:
                _c.destroy(h)

    destrptr = gctransformer.annotate_helper(shadowstack_destructor,
                                             [SHADOWSTACKREFPTR], lltype.Void)

    lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, destrptr=destrptr)

    gctransformer._SHADOWSTACKREF = SHADOWSTACKREF
    return SHADOWSTACKREF
Exemple #7
0
class TestConstPtr(BaseTestRegalloc):

    cpu = CPU(None, None)
    #cpu.gc_ll_descr = MockGcDescr(False)
    cpu.setup_once()

    S = lltype.GcForwardReference()
    fields = [('int%d' % i, lltype.Signed) for i in range(1050)]
    S.become(lltype.GcStruct('S', *fields))

    fielddescr = cpu.fielddescrof(S, 'int1049')

    struct_ptr = lltype.malloc(S)
    struct_ref = lltype.cast_opaque_ptr(llmemory.GCREF, struct_ptr)

    ptr0 = struct_ref

    namespace = locals().copy()

    def test_finish_failargs_constptr(self):
        ops = '''
        [i0]
        i1 = int_add(i0, 1)
        finish(ConstPtr(ptr0))
        '''
        loop = self.interpret(ops, [99])
        ptr = self.getptr(0, lltype.Ptr(self.S))
        assert self.struct_ptr == ptr

    def test_getfield_with_offset_gt_one_byte(self):
        self.struct_ptr.int1049 = 666
        ops = '''
        [p0]
        i0 = getfield_gc(p0, descr=fielddescr)
        finish(i0)
        '''
        self.interpret(ops, [self.struct_ptr])
        assert self.getint(0) == 666

    def test_setfield_with_offset_gt_one_byte(self):
        ops = '''
        [p0]
        setfield_gc(p0, 777, descr=fielddescr)
        finish()
        '''
        self.interpret(ops, [self.struct_ptr])
        assert self.struct_ptr.int1049 == 777
Exemple #8
0
    def define_compile_framework_call_assembler(self):
        S = lltype.GcForwardReference()
        S.become(lltype.GcStruct('S', ('s', lltype.Ptr(S))))
        driver = JitDriver(greens=[], reds='auto', is_recursive=True)

        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s0):
            driver.jit_merge_point()
            i = 0
            prev_s = lltype.nullptr(S)
            while i < 100:
                s = lltype.malloc(S)
                s.s = prev_s
                prev_s = s
                i += 1
            return n - 1, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s0

        return None, f, None
    def define_write_barrier_direct(cls):
        from rpython.rlib import rgc
        S = lltype.GcForwardReference()
        S.become(
            lltype.GcStruct('S', ('x', lltype.Signed), ('prev', lltype.Ptr(S)),
                            ('next', lltype.Ptr(S))))
        s0 = lltype.malloc(S, immortal=True)

        def f():
            s = lltype.malloc(S)
            s.x = 42
            llop.bare_setfield(lltype.Void, s0, void('next'), s)
            llop.gc_writebarrier(lltype.Void, llmemory.cast_ptr_to_adr(s0))
            rgc.collect(0)
            return s0.next.x

        def cleanup():
            s0.next = lltype.nullptr(S)

        return f, cleanup, None
Exemple #10
0
def get_shadowstackref(root_walker, gctransformer):
    if hasattr(gctransformer, '_SHADOWSTACKREF'):
        return gctransformer._SHADOWSTACKREF

    SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference())
    SHADOWSTACKREF = lltype.GcStruct('ShadowStackRef',
                                     ('base', llmemory.Address),
                                     ('top', llmemory.Address),
                                     rtti=True)
    SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF)

    def customtrace(gc, obj, callback, arg1, arg2):
        obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
        walk_stack_root(gc._trace_callback,
                        callback,
                        arg1,
                        arg2,
                        obj.base,
                        obj.top,
                        is_minor=False)  # xxx optimize?

    gc = gctransformer.gcdata.gc
    assert not hasattr(gc, 'custom_trace_dispatcher')
    # ^^^ create_custom_trace_funcs() must not run before this
    gctransformer.translator.rtyper.custom_trace_funcs.append(
        (SHADOWSTACKREF, customtrace))

    def shadowstack_destructor(shadowstackref):
        base = shadowstackref.base
        shadowstackref.base = llmemory.NULL
        shadowstackref.top = llmemory.NULL
        llmemory.raw_free(base)

    destrptr = gctransformer.annotate_helper(shadowstack_destructor,
                                             [SHADOWSTACKREFPTR], lltype.Void)

    lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, destrptr=destrptr)

    gctransformer._SHADOWSTACKREF = SHADOWSTACKREF
    return SHADOWSTACKREF
Exemple #11
0
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()
Exemple #12
0
 def _get_NODE(self):
     NODE = lltype.GcForwardReference()
     NODE.become(
         lltype.GcStruct('NODE', ('value', lltype.Signed),
                         ('next', lltype.Ptr(NODE))))
     return NODE
Exemple #13
0
class TestRegallocGcIntegration(BaseTestRegalloc):

    cpu = CPU(None, None)
    cpu.gc_ll_descr = GcLLDescr_boehm(None, None, None)
    cpu.setup_once()

    S = lltype.GcForwardReference()
    S.become(lltype.GcStruct('S', ('field', lltype.Ptr(S)),
                             ('int', lltype.Signed)))

    fielddescr = cpu.fielddescrof(S, 'field')

    struct_ptr = lltype.malloc(S)
    struct_ref = lltype.cast_opaque_ptr(llmemory.GCREF, struct_ptr)
    child_ptr = lltype.nullptr(S)
    struct_ptr.field = child_ptr


    intdescr = cpu.fielddescrof(S, 'int')
    ptr0 = struct_ref

    targettoken = TargetToken()
    targettoken2 = TargetToken()

    namespace = locals().copy()

    def test_basic(self):
        ops = '''
        [p0]
        p1 = getfield_gc_r(p0, descr=fielddescr)
        finish(p1)
        '''
        self.interpret(ops, [self.struct_ptr])
        assert not self.getptr(0, lltype.Ptr(self.S))

    def test_guard(self):
        ops = '''
        [i0, p0, i1, p1]
        p3 = getfield_gc_r(p0, descr=fielddescr)
        guard_true(i0) [p0, i1, p1, p3]
        '''
        s1 = lltype.malloc(self.S)
        s2 = lltype.malloc(self.S)
        s1.field = s2
        self.interpret(ops, [0, s1, 1, s2])
        frame = lltype.cast_opaque_ptr(jitframe.JITFRAMEPTR, self.deadframe)
        # p0 and p3 should be in registers, p1 not so much
        assert self.getptr(0, lltype.Ptr(self.S)) == s1
        # the gcmap should contain three things, p0, p1 and p3
        # p3 stays in a register
        # while p0 and p1 are on the frame
        b = getmap(frame)
        nos = [len(b) - 1 - i.start() for i in re.finditer('1', b)]
        nos.reverse()
        if self.cpu.backend_name.startswith('x86'):
            if self.cpu.IS_64_BIT:
                assert nos == [0, 1, 31]
            else:
                assert nos ==  [0, 1, 25]
        elif self.cpu.backend_name.startswith('arm'):
            assert nos == [0, 1, 47]
        elif self.cpu.backend_name.startswith('ppc64'):
            assert nos == [0, 1, 33]
        elif self.cpu.backend_name.startswith('zarch'):
            assert nos == [0, 1, 29]
        else:
            raise Exception("write the data here")
        assert frame.jf_frame[nos[0]]
        assert frame.jf_frame[nos[1]]
        assert frame.jf_frame[nos[2]]

    def test_rewrite_constptr(self):
        ops = '''
        []
        p1 = getfield_gc_r(ConstPtr(struct_ref), descr=fielddescr)
        finish(p1)
        '''
        self.interpret(ops, [])
        assert not self.getptr(0, lltype.Ptr(self.S))

    def test_bug_0(self):
        ops = '''
        [i0, i1, i2, i3, i4, i5, i6, i7, i8]
        label(i0, i1, i2, i3, i4, i5, i6, i7, i8, descr=targettoken)
        guard_value(i2, 1) [i2, i3, i4, i5, i6, i7, i0, i1, i8]
        guard_class(i4, 138998336) [i4, i5, i6, i7, i0, i1, i8]
        i11 = getfield_gc_i(i4, descr=intdescr)
        guard_nonnull(i11) [i4, i5, i6, i7, i0, i1, i11, i8]
        i13 = getfield_gc_i(i11, descr=intdescr)
        guard_isnull(i13) [i4, i5, i6, i7, i0, i1, i11, i8]
        i15 = getfield_gc_i(i4, descr=intdescr)
        i17 = int_lt(i15, 0)
        guard_false(i17) [i4, i5, i6, i7, i0, i1, i11, i15, i8]
        i18 = getfield_gc_i(i11, descr=intdescr)
        i19 = int_ge(i15, i18)
        guard_false(i19) [i4, i5, i6, i7, i0, i1, i11, i15, i8]
        i20 = int_lt(i15, 0)
        guard_false(i20) [i4, i5, i6, i7, i0, i1, i11, i15, i8]
        i21 = getfield_gc_i(i11, descr=intdescr)
        i22 = getfield_gc_i(i11, descr=intdescr)
        i23 = int_mul(i15, i22)
        i24 = int_add(i21, i23)
        i25 = getfield_gc_i(i4, descr=intdescr)
        i27 = int_add(i25, 1)
        setfield_gc(i4, i27, descr=intdescr)
        i29 = getfield_raw_i(144839744, descr=intdescr)
        i31 = int_and(i29, -2141192192)
        i32 = int_is_true(i31)
        guard_false(i32) [i4, i6, i7, i0, i1, i24]
        i33 = getfield_gc_i(i0, descr=intdescr)
        guard_value(i33, ConstPtr(ptr0)) [i4, i6, i7, i0, i1, i33, i24]
        jump(i0, i1, 1, 17, i4, ConstPtr(ptr0), i6, i7, i24, descr=targettoken)
        '''
        self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0, 0], run=False)
Exemple #14
0
from rpython.rtyper.rbytearray import AbstractByteArrayRepr
from rpython.rtyper.lltypesystem import lltype, rstr
from rpython.rlib.debug import ll_assert

BYTEARRAY = lltype.GcForwardReference()


def mallocbytearray(size):
    return lltype.malloc(BYTEARRAY, size)


_, _, copy_bytearray_contents = rstr._new_copy_contents_fun(
    BYTEARRAY, BYTEARRAY, lltype.Char, 'bytearray')
_, _, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun(
    rstr.STR, BYTEARRAY, lltype.Char, 'bytearray_from_str')


def _empty_bytearray():
    return empty


BYTEARRAY.become(
    lltype.GcStruct(
        'rpy_bytearray', ('chars', lltype.Array(lltype.Char)),
        adtmeths={
            'malloc':
            lltype.staticAdtMethod(mallocbytearray),
            'copy_contents':
            lltype.staticAdtMethod(copy_bytearray_contents),
            'copy_contents_from_str':
            lltype.staticAdtMethod(copy_bytearray_contents_from_str),
Exemple #15
0
# ------------------------------------------------------------


def dont_inline(func):
    func._dont_inline_ = True
    return func


def always_inline(func):
    func._always_inline_ = True
    return func


STRINGPIECE = lltype.GcStruct(
    'stringpiece', ('buf', lltype.Ptr(STR)),
    ('prev_piece', lltype.Ptr(lltype.GcForwardReference())))
STRINGPIECE.prev_piece.TO.become(STRINGPIECE)

STRINGBUILDER = lltype.GcStruct('stringbuilder',
                                ('current_buf', lltype.Ptr(STR)),
                                ('current_pos', lltype.Signed),
                                ('current_end', lltype.Signed),
                                ('total_size', lltype.Signed),
                                ('extra_pieces', lltype.Ptr(STRINGPIECE)),
                                adtmeths={
                                    'copy_string_contents':
                                    staticAdtMethod(rstr.copy_string_contents),
                                    'copy_raw_to_string':
                                    staticAdtMethod(rstr.copy_raw_to_string),
                                    'mallocfn':
                                    staticAdtMethod(rstr.mallocstr),
Exemple #16
0
class BlockBuilderMixin(object):
    _mixin_ = True
    # A base class to generate assembler.  It is equivalent to just a list
    # of chars, but it is potentially more efficient for that usage.
    # It works by allocating the assembler SUBBLOCK_SIZE bytes at a time.
    # Ideally, this number should be a power of two that fits the GC's most
    # compact allocation scheme (which is so far 35 * WORD for minimark.py).
    WORD = LONG_BIT // 8
    SUBBLOCK_SIZE = 32 * WORD
    SUBBLOCK_PTR = lltype.Ptr(lltype.GcForwardReference())
    SUBBLOCK = lltype.GcStruct(
        'SUBBLOCK', ('prev', SUBBLOCK_PTR),
        ('data', lltype.FixedSizeArray(lltype.Char, SUBBLOCK_SIZE)))
    SUBBLOCK_PTR.TO.become(SUBBLOCK)

    ALIGN_MATERIALIZE = 16

    gcroot_markers = None

    def __init__(self, translated=None):
        if translated is None:
            translated = we_are_translated()
        if translated:
            self.init_block_builder()
        else:
            self._become_a_plain_block_builder()
        self.rawstart = 0

    def init_block_builder(self):
        self._cursubblock = lltype.nullptr(self.SUBBLOCK)
        self._baserelpos = -self.SUBBLOCK_SIZE
        self._make_new_subblock()

    def _make_new_subblock(self):
        nextsubblock = lltype.malloc(self.SUBBLOCK)
        nextsubblock.prev = self._cursubblock
        self._cursubblock = nextsubblock
        self._cursubindex = 0
        self._baserelpos += self.SUBBLOCK_SIZE

    _make_new_subblock._dont_inline_ = True

    def writechar(self, char):
        index = self._cursubindex
        if index == self.SUBBLOCK_SIZE:
            self._make_new_subblock()
            index = 0
        self._cursubblock.data[index] = char
        self._cursubindex = index + 1

    def absolute_addr(self):
        return self.rawstart

    def overwrite(self, index, char):
        assert 0 <= index < self.get_relative_pos()
        block = self._cursubblock
        index -= self._baserelpos
        while index < 0:
            block = block.prev
            index += self.SUBBLOCK_SIZE
        block.data[index] = char

    def overwrite32(self, index, val):
        self.overwrite(index, chr(val & 0xff))
        self.overwrite(index + 1, chr((val >> 8) & 0xff))
        self.overwrite(index + 2, chr((val >> 16) & 0xff))
        self.overwrite(index + 3, chr((val >> 24) & 0xff))

    def get_relative_pos(self):
        return self._baserelpos + self._cursubindex

    def copy_to_raw_memory(self, addr):
        # indirection for _become_a_plain_block_builder() and for subclasses
        self._copy_to_raw_memory(addr)

    def _copy_to_raw_memory(self, addr):
        block = self._cursubblock
        blocksize = self._cursubindex
        targetindex = self._baserelpos
        while targetindex >= 0:
            dst = rffi.cast(rffi.CCHARP, addr + targetindex)
            for j in range(blocksize):
                dst[j] = block.data[j]
            block = block.prev
            blocksize = self.SUBBLOCK_SIZE
            targetindex -= self.SUBBLOCK_SIZE
        assert not block

    def copy_core_dump(self, addr, offset=0, count=-1):
        HEX = '0123456789ABCDEF'
        dump = []
        src = rffi.cast(rffi.CCHARP, addr)
        end = self.get_relative_pos()
        if count != -1:
            end = offset + count
        for p in range(offset, end):
            o = ord(src[p])
            dump.append(HEX[o >> 4])
            dump.append(HEX[o & 15])
        return ''.join(dump)

    def _dump(self, addr, logname, backend=None):
        debug_start(logname)
        if have_debug_prints():
            #
            if backend is not None:
                debug_print('BACKEND', backend)
            #
            from rpython.jit.backend.hlinfo import highleveljitinfo
            if highleveljitinfo.sys_executable:
                debug_print('SYS_EXECUTABLE', highleveljitinfo.sys_executable)
            else:
                debug_print('SYS_EXECUTABLE', '??')
            #
            dump = self.copy_core_dump(addr)
            debug_print(
                'CODE_DUMP',
                '@%x' % addr,
                '+0 ',  # backwards compatibility
                dump)
            #
        debug_stop(logname)

    def materialize(self, cpu, allblocks, gcrootmap=None):
        size = self.get_relative_pos()
        align = self.ALIGN_MATERIALIZE
        size += align - 1
        malloced = cpu.asmmemmgr.malloc(size, size)
        allblocks.append(malloced)
        rawstart = malloced[0]
        rawstart = (rawstart + align - 1) & (-align)
        self.rawstart = rawstart
        self.copy_to_raw_memory(rawstart)
        if self.gcroot_markers is not None:
            assert gcrootmap is not None
            for pos, mark in self.gcroot_markers:
                gcrootmap.register_asm_addr(rawstart + pos, mark)
        return rawstart

    def _become_a_plain_block_builder(self):
        # hack purely for speed of tests
        self._data = []
        self.writechar = self._data.append
        self.overwrite = self._data.__setitem__
        self.get_relative_pos = self._data.__len__

        def plain_copy_to_raw_memory(addr):
            dst = rffi.cast(rffi.CCHARP, addr)
            for i, c in enumerate(self._data):
                dst[i] = c

        self._copy_to_raw_memory = plain_copy_to_raw_memory

    def insert_gcroot_marker(self, mark):
        if self.gcroot_markers is None:
            self.gcroot_markers = []
        self.gcroot_markers.append((self.get_relative_pos(), mark))
Exemple #17
0
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()
Exemple #18
0
def get_shadowstackref(root_walker, gctransformer):
    if hasattr(gctransformer, '_SHADOWSTACKREF'):
        return gctransformer._SHADOWSTACKREF

    # Helpers to same virtual address space by limiting to MAX the
    # number of full shadow stacks.  If there are more, we compact
    # them into a separately-allocated zone of memory of just the right
    # size.  See the comments in the definition of fullstack_cache below.

    def ll_prepare_free_slot(_unused):
        """Free up a slot in the array of MAX entries, ready for storing
        a new shadowstackref.  Return the memory of the now-unused full
        shadowstack.
        """
        index = fullstack_cache[0]
        if index > 0:
            return llmemory.NULL     # there is already at least one free slot
        #
        # make a compact copy in one old entry and return the
        # original full-sized memory
        index = -index
        ll_assert(index > 0, "prepare_free_slot: cache[0] == 0")
        compacting = lltype.cast_int_to_ptr(SHADOWSTACKREFPTR,
                                            fullstack_cache[index])
        index += 1
        if index >= ShadowStackPool.MAX:
            index = 1
        fullstack_cache[0] = -index    # update to the next value in order
        #
        compacting.detach()
        original = compacting.base
        size = compacting.top - original
        new = llmemory.raw_malloc(size)
        if new == llmemory.NULL:
            return llmemory.NULL
        llmemory.raw_memcopy(original, new, size)
        compacting.base = new
        compacting.top = new + size
        return original

    def ll_attach(shadowstackref):
        """After prepare_free_slot(), store a shadowstackref in that slot."""
        index = fullstack_cache[0]
        ll_assert(index > 0, "fullstack attach: no free slot")
        fullstack_cache[0] = fullstack_cache[index]
        fullstack_cache[index] = lltype.cast_ptr_to_int(shadowstackref)
        ll_assert(shadowstackref.fsindex == 0, "fullstack attach: already one?")
        shadowstackref.fsindex = index    # > 0

    def ll_detach(shadowstackref):
        """Detach a shadowstackref from the array of MAX entries."""
        index = shadowstackref.fsindex
        ll_assert(index > 0, "detach: unattached shadowstackref")
        ll_assert(fullstack_cache[index] ==
                  lltype.cast_ptr_to_int(shadowstackref),
                  "detach: bad fullstack_cache")
        shadowstackref.fsindex = 0
        fullstack_cache[index] = fullstack_cache[0]
        fullstack_cache[0] = index

    def ll_rebuild(shadowstackref, fullstack_base):
        if shadowstackref.fsindex > 0:
            shadowstackref.detach()
            return fullstack_base
        else:
            # make an expanded copy of the compact shadowstack stored in
            # 'shadowstackref' and free that
            compact = shadowstackref.base
            size = shadowstackref.top - compact
            shadowstackref.base = fullstack_base
            shadowstackref.top = fullstack_base + size
            llmemory.raw_memcopy(compact, fullstack_base, size)
            llmemory.raw_free(compact)
            return llmemory.NULL

    SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference())
    SHADOWSTACKREF = lltype.GcStruct('ShadowStackRef',
        ('base', llmemory.Address),
        ('top', llmemory.Address),
        ('context', llmemory.Address),
        ('fsindex', lltype.Signed),
        rtti=True,
        adtmeths={'prepare_free_slot': ll_prepare_free_slot,
                  'attach': ll_attach,
                  'detach': ll_detach,
                  'rebuild': ll_rebuild})
    SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF)

    # Items 1..MAX-1 of the following array can be SHADOWSTACKREF
    # addresses cast to integer.  Or, they are small numbers and they
    # make up a free list, rooted in item 0, which goes on until
    # terminated with a negative item.  This negative item gives (the
    # opposite of) the index of the entry we try to remove next.
    # Initially all items are in this free list and the end is '-1'.
    fullstack_cache = lltype.malloc(lltype.Array(lltype.Signed),
                                    ShadowStackPool.MAX,
                                    flavor='raw', immortal=True)
    for i in range(len(fullstack_cache) - 1):
        fullstack_cache[i] = i + 1
    fullstack_cache[len(fullstack_cache) - 1] = -1

    def customtrace(gc, obj, callback, arg):
        obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
        index = obj.fsindex
        if index > 0:
            # Haaaaaaack: fullstack_cache[] is just an integer, so it
            # doesn't follow the SHADOWSTACKREF when it moves.  But we
            # know this customtrace() will be called just after the
            # move.  So we fix the fullstack_cache[] now... :-/
            fullstack_cache[index] = lltype.cast_ptr_to_int(obj)
        addr = obj.top
        start = obj.base
        while addr != start:
            addr -= sizeofaddr
            gc._trace_callback(callback, arg, addr)

    gc = gctransformer.gcdata.gc
    assert not hasattr(gc, 'custom_trace_dispatcher')
    # ^^^ create_custom_trace_funcs() must not run before this
    gctransformer.translator.rtyper.custom_trace_funcs.append(
        (SHADOWSTACKREF, customtrace))

    def shadowstack_destructor(shadowstackref):
        if root_walker.stacklet_support:
            from rpython.rlib import _rffi_stacklet as _c
            h = shadowstackref.context
            h = llmemory.cast_adr_to_ptr(h, _c.handle)
            shadowstackref.context = llmemory.NULL
        #
        if shadowstackref.fsindex > 0:
            shadowstackref.detach()
        base = shadowstackref.base
        shadowstackref.base    = llmemory.NULL
        shadowstackref.top     = llmemory.NULL
        llmemory.raw_free(base)
        #
        if root_walker.stacklet_support:
            if h:
                _c.destroy(h)

    destrptr = gctransformer.annotate_helper(shadowstack_destructor,
                                             [SHADOWSTACKREFPTR], lltype.Void)

    lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, destrptr=destrptr)

    gctransformer._SHADOWSTACKREF = SHADOWSTACKREF
    return SHADOWSTACKREF
Exemple #19
0
class TestARM(LLtypeBackendTest):

    # for the individual tests see
    # ====> ../../test/runner_test.py

    add_loop_instructions = 'ldr; adds; cmp; beq; b;'
    arch_version = detect_arch_version()
    if arch_version == 7:
        bridge_loop_instructions = ('ldr; movw; nop; cmp; bge; '
                                    'push; movw; movt; push; movw; movt; '
                                    'blx; movw; movt; bx;')
    else:
        bridge_loop_instructions = (
            'ldr; mov; nop; nop; nop; cmp; bge; '
            'push; ldr; mov; '
            '[^;]+; '  # inline constant
            'push; ldr; mov; '
            '[^;]+; '  # inline constant
            'blx; ldr; mov; '
            '[^;]+; '  # inline constant
            'bx;')

    def get_cpu(self):
        cpu = CPU(rtyper=None, stats=FakeStats())
        cpu.setup_once()
        return cpu

    def test_result_is_spilled(self):
        cpu = self.cpu
        inp = [InputArgInt(i) for i in range(1, 15)]
        looptoken = JitCellToken()
        targettoken = TargetToken()
        operations = [
            ResOperation(rop.LABEL, inp, descr=targettoken),
            ResOperation(rop.INT_ADD, [inp[0], inp[1]]),
            ResOperation(rop.INT_ADD, [inp[2], inp[3]]),
            ResOperation(rop.INT_ADD, [inp[4], inp[5]]),
            ResOperation(rop.INT_ADD, [inp[6], inp[7]]),
            ResOperation(rop.INT_ADD, [inp[8], inp[9]]),
            ResOperation(rop.INT_ADD, [inp[10], inp[11]]),
            ResOperation(rop.INT_ADD, [inp[12], inp[13]]),
            ResOperation(rop.INT_ADD, [inp[0], inp[1]]),
            ResOperation(rop.INT_ADD, [inp[2], inp[3]]),
            ResOperation(rop.INT_ADD, [inp[4], inp[5]]),
            ResOperation(rop.INT_ADD, [inp[6], inp[7]]),
            ResOperation(rop.INT_ADD, [inp[8], inp[9]]),
            ResOperation(rop.INT_ADD, [inp[10], inp[11]]),
            ResOperation(rop.INT_ADD, [inp[12], inp[13]]),
            ResOperation(rop.GUARD_FALSE, [inp[1]], descr=BasicFailDescr(1)),
            ResOperation(rop.FINISH, [inp[1]], descr=BasicFinalDescr(1)),
        ]
        operations[-2].setfailargs(operations[1:15])
        cpu.compile_loop(inp, operations, looptoken)
        args = [i for i in range(1, 15)]
        deadframe = self.cpu.execute_token(looptoken, *args)
        output = [
            self.cpu.get_int_value(deadframe, i - 1) for i in range(1, 15)
        ]
        expected = [3, 7, 11, 15, 19, 23, 27, 3, 7, 11, 15, 19, 23, 27]
        assert output == expected

    def test_redirect_call_assembler2(self):
        def assembler_helper(deadframe, virtualizable):
            x = self.cpu.get_int_value(deadframe, 0)
            assert x == 11
            return 7

        FUNCPTR = lltype.Ptr(
            lltype.FuncType([llmemory.GCREF, llmemory.GCREF], lltype.Signed))

        class FakeJitDriverSD:
            index_of_virtualizable = -1
            _assembler_helper_ptr = llhelper(FUNCPTR, assembler_helper)
            assembler_helper_adr = llmemory.cast_ptr_to_adr(
                _assembler_helper_ptr)

        FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
            lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed)),
            [lltype.Signed], lltype.Signed, EffectInfo.MOST_GENERAL)
        lt1, lt2, lt3 = [JitCellToken() for x in range(3)]
        lt2.outermost_jitdriver_sd = FakeJitDriverSD()
        loop1 = parse('''
        [i0]
        i1 = call_assembler_i(i0, descr=lt2)
        guard_not_forced()[]
        finish(i1)
        ''',
                      namespace=locals())
        loop2 = parse('''
        [i0]
        i1 = int_add(i0, 1)
        finish(i1)
        ''')
        loop3 = parse('''
        [i0]
        i1 = int_sub(i0, 1)
        finish(i1)
        ''')
        self.cpu.compile_loop(loop2.inputargs, loop2.operations, lt2)
        self.cpu.compile_loop(loop3.inputargs, loop3.operations, lt3)
        self.cpu.compile_loop(loop1.inputargs, loop1.operations, lt1)
        df = self.cpu.execute_token(lt1, 10)
        assert self.cpu.get_int_value(df, 0) == 7

        self.cpu.redirect_call_assembler(lt2, lt3)
        df = self.cpu.execute_token(lt1, 12)
        assert self.cpu.get_int_value(df, 0) == 7

    SFloat = lltype.GcForwardReference()
    SFloat.become(
        lltype.GcStruct('SFloat', ('parent', rclass.OBJECT),
                        ('v1', lltype.Signed), ('v2', lltype.Signed),
                        ('v3', lltype.Signed), ('v4', lltype.Signed),
                        ('v5', lltype.Signed), ('v6', lltype.Signed),
                        ('v7', lltype.Signed), ('v8', lltype.Signed),
                        ('v9', lltype.Signed), ('v10', lltype.Signed),
                        ('v11', lltype.Signed), ('v12', lltype.Signed),
                        ('v13', lltype.Signed), ('v14', lltype.Signed),
                        ('v15', lltype.Signed), ('v16', lltype.Signed),
                        ('v17', lltype.Signed), ('v18', lltype.Signed),
                        ('v19', lltype.Signed), ('v20', lltype.Signed),
                        ('w1', lltype.Signed), ('w2', lltype.Signed),
                        ('w3', lltype.Signed), ('w4', lltype.Signed),
                        ('w5', lltype.Signed), ('w6', lltype.Signed),
                        ('w7', lltype.Signed), ('w8', lltype.Signed),
                        ('w9', lltype.Signed), ('w10', lltype.Signed),
                        ('w11', lltype.Signed), ('w12', lltype.Signed),
                        ('w13', lltype.Signed), ('w14', lltype.Signed),
                        ('w15', lltype.Signed), ('w16', lltype.Signed),
                        ('w17', lltype.Signed), ('w18', lltype.Signed),
                        ('w19', lltype.Signed), ('w20', lltype.Signed),
                        ('x1', lltype.Signed), ('x2', lltype.Signed),
                        ('x3', lltype.Signed), ('x4', lltype.Signed),
                        ('x5', lltype.Signed), ('x6', lltype.Signed),
                        ('x7', lltype.Signed), ('x8', lltype.Signed),
                        ('x9', lltype.Signed), ('x10', lltype.Signed),
                        ('x11', lltype.Signed), ('x12', lltype.Signed),
                        ('x13', lltype.Signed), ('x14', lltype.Signed),
                        ('x15', lltype.Signed), ('x16', lltype.Signed),
                        ('x17', lltype.Signed), ('x18', lltype.Signed),
                        ('x19', lltype.Signed), ('x20', lltype.Signed),
                        ('y1', lltype.Signed), ('y2', lltype.Signed),
                        ('y3', lltype.Signed), ('y4', lltype.Signed),
                        ('y5', lltype.Signed), ('y6', lltype.Signed),
                        ('y7', lltype.Signed), ('y8', lltype.Signed),
                        ('y9', lltype.Signed), ('y10', lltype.Signed),
                        ('y11', lltype.Signed), ('y12', lltype.Signed),
                        ('y13', lltype.Signed), ('y14', lltype.Signed),
                        ('y15', lltype.Signed), ('y16', lltype.Signed),
                        ('y17', lltype.Signed), ('y18', lltype.Signed),
                        ('y19', lltype.Signed), ('y20', lltype.Signed),
                        ('float', lltype.Float)))

    TFloat = lltype.GcStruct('TFloat', ('parent', SFloat),
                             ('next', lltype.Ptr(SFloat)))

    def test_float_field(self):
        if not self.cpu.supports_floats:
            py.test.skip('requires floats')
        t_box, T_box, _ = self.alloc_instance(self.TFloat)
        floatdescr = self.cpu.fielddescrof(self.SFloat, 'float')
        self.execute_operation(rop.SETFIELD_GC, [t_box, boxfloat(3.4)],
                               'void',
                               descr=floatdescr)
        res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
                                     'float',
                                     descr=floatdescr)
        assert longlong.getrealfloat(res) == 3.4
        #
        self.execute_operation(rop.SETFIELD_GC,
                               [t_box, constfloat(-3.6)],
                               'void',
                               descr=floatdescr)
        res = self.execute_operation(rop.GETFIELD_GC_F, [t_box],
                                     'float',
                                     descr=floatdescr)
        assert longlong.getrealfloat(res) == -3.6

    def test_compile_loop_many_int_args(self):
        for numargs in range(2, 30):
            ops = []
            arglist = "[%s]\n" % ", ".join(["i%d" % i for i in range(numargs)])
            ops.append(arglist)

            arg1 = 0
            arg2 = 1
            res = numargs
            for i in range(numargs - 1):
                op = "i%d = int_add(i%d, i%d)\n" % (res, arg1, arg2)
                arg1 = res
                res += 1
                arg2 += 1
                ops.append(op)
            ops.append("finish(i%d)" % (res - 1))

            ops = "".join(ops)
            loop = parse(ops)
            looptoken = JitCellToken()
            self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
            ARGS = [lltype.Signed] * numargs
            RES = lltype.Signed
            args = [i + 1 for i in range(numargs)]
            deadframe = self.cpu.execute_token(looptoken, *args)
            assert self.cpu.get_int_value(deadframe, 0) == sum(args)

    def test_debugger_on(self):
        py.test.skip("I don't care for now")
        from rpython.rlib import debug

        targettoken, preambletoken = TargetToken(), TargetToken()
        loop = """
        [i0]
        label(i0, descr=preambletoken)
        debug_merge_point('xyz', 0)
        i1 = int_add(i0, 1)
        i2 = int_ge(i1, 10)
        guard_false(i2) []
        label(i1, descr=targettoken)
        debug_merge_point('xyz', 0)
        i11 = int_add(i1, 1)
        i12 = int_ge(i11, 10)
        guard_false(i12) []
        jump(i11, descr=targettoken)
        """
        ops = parse(loop,
                    namespace={
                        'targettoken': targettoken,
                        'preambletoken': preambletoken
                    })
        debug._log = dlog = debug.DebugLog()
        try:
            self.cpu.assembler.set_debug(True)
            looptoken = JitCellToken()
            self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken)
            self.cpu.execute_token(looptoken, 0)
            # check debugging info
            struct = self.cpu.assembler.loop_run_counters[0]
            assert struct.i == 1
            struct = self.cpu.assembler.loop_run_counters[1]
            assert struct.i == 1
            struct = self.cpu.assembler.loop_run_counters[2]
            assert struct.i == 9
            self.cpu.finish_once()
        finally:
            debug._log = None
        l0 = ('debug_print', 'entry -1:1')
        l1 = ('debug_print', preambletoken.repr_of_descr() + ':1')
        l2 = ('debug_print', targettoken.repr_of_descr() + ':9')
        assert ('jit-backend-counts', [l0, l1, l2]) in dlog

    def test_label_float_in_reg_and_on_stack(self):
        targettoken = TargetToken()
        ops = """
        [i0, f3]
        i2 = same_as_i(i0)    # but forced to be in a register
        force_spill(i2)
        force_spill(f3)
        f4 = float_add(f3, 5.0)
        label(f3, f4, descr=targettoken)
        force_spill(f3)
        f5 = same_as_f(f3)    # but forced to be in a register
        finish(f5)
        """
        faildescr = BasicFailDescr(2)
        loop = parse(ops, self.cpu, namespace=locals())
        looptoken = JitCellToken()
        info = self.cpu.compile_loop(loop.inputargs, loop.operations,
                                     looptoken)
        ops2 = """
        [i0, f1]
        i1 = same_as_i(i0)
        f2 = same_as_f(f1)
        f3 = float_add(f1, 10.0)
        force_spill(f3)
        force_spill(i1)
        f4 = float_add(f3, f1)
        jump(f3, f4, descr=targettoken)
        """
        loop2 = parse(ops2, self.cpu, namespace=locals())
        looptoken2 = JitCellToken()
        info = self.cpu.compile_loop(loop2.inputargs, loop2.operations,
                                     looptoken2)

        deadframe = self.cpu.execute_token(looptoken, -9,
                                           longlong.getfloatstorage(-13.5))
        res = longlong.getrealfloat(self.cpu.get_float_value(deadframe, 0))
        assert res == -13.5
        #
        deadframe = self.cpu.execute_token(looptoken2, -9,
                                           longlong.getfloatstorage(-13.5))
        res = longlong.getrealfloat(self.cpu.get_float_value(deadframe, 0))
        assert res == -3.5
Exemple #20
0
  [<length> <virtual> <vref> <virtual> <vref>]     for virtualrefs

  [<pc> <jitcode> <numb> <numb> <numb>]            the frames
  [<pc> <jitcode> <numb> <numb>]
  ...

  until the size of the resume section

  # ----- optimization section
  <more code>                                      further sections according to bridgeopt.py
"""

from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import objectmodel

NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
NUMBERING = lltype.GcStruct('Numbering', ('code', lltype.Array(rffi.UCHAR)))
NUMBERINGP.TO.become(NUMBERING)
NULL_NUMBER = lltype.nullptr(NUMBERING)


def append_numbering(lst, item):
    item = rffi.cast(lltype.Signed, item)
    item *= 2
    if item < 0:
        item = -1 - item

    assert item >= 0
    if item < 2**7:
        lst.append(rffi.cast(rffi.UCHAR, item))
    elif item < 2**14:
Exemple #21
0

def jitframe_allocate(frame_info):
    rgc.register_custom_trace_hook(JITFRAME, lambda_jitframe_trace)
    frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth)
    frame.jf_frame_info = frame_info
    return frame


def jitframe_resolve(frame):
    while frame.jf_forward:
        frame = frame.jf_forward
    return frame


JITFRAME = lltype.GcForwardReference()

JITFRAME.become(
    lltype.GcStruct(
        'JITFRAME',
        ('jf_frame_info', lltype.Ptr(JITFRAMEINFO)),
        # Once the execute_token() returns, the field 'jf_descr' stores the
        # descr of the last executed operation (either a GUARD, or FINISH).
        # This field is also set immediately before doing CALL_MAY_FORCE
        # or CALL_ASSEMBLER.
        ('jf_descr', llmemory.GCREF),
        # guard_not_forced descr
        ('jf_force_descr', llmemory.GCREF),
        # a map of GC pointers
        ('jf_gcmap', lltype.Ptr(GCMAP)),
        # For the front-end: a GCREF for the savedata
Exemple #22
0
import py
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.memory.gc.incminimark import IncrementalMiniMarkGC
from rpython.memory.gc.test.test_direct import BaseDirectGCTest
from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT

PYOBJ_HDR = IncrementalMiniMarkGC.PYOBJ_HDR
PYOBJ_HDR_PTR = IncrementalMiniMarkGC.PYOBJ_HDR_PTR

S = lltype.GcForwardReference()
S.become(
    lltype.GcStruct('S', ('x', lltype.Signed), ('prev', lltype.Ptr(S)),
                    ('next', lltype.Ptr(S))))


class TestRawRefCount(BaseDirectGCTest):
    GCClass = IncrementalMiniMarkGC

    def _collect(self, major, expected_trigger=0):
        if major:
            self.gc.collect()
        else:
            self.gc._minor_collection()
        count1 = len(self.trigger)
        self.gc.rrc_invoke_callback()
        count2 = len(self.trigger)
        assert count2 - count1 == expected_trigger

    def _rawrefcount_pair(self,
                          intval,
Exemple #23
0
def get_ll_dict(DICTKEY,
                DICTVALUE,
                get_custom_eq_hash=None,
                DICT=None,
                ll_fasthash_function=None,
                ll_hash_function=None,
                ll_eq_function=None,
                method_cache={},
                dummykeyobj=None,
                dummyvalueobj=None,
                rtyper=None):
    # get the actual DICT type. if DICT is None, it's created, otherwise
    # forward reference is becoming DICT
    if DICT is None:
        DICT = lltype.GcForwardReference()
    # compute the shape of the DICTENTRY structure
    entryfields = []
    entrymeths = {
        'allocate':
        lltype.typeMethod(_ll_malloc_entries),
        'delete':
        _ll_free_entries,
        'must_clear_key': (isinstance(DICTKEY, lltype.Ptr)
                           and DICTKEY._needsgc()),
        'must_clear_value': (isinstance(DICTVALUE, lltype.Ptr)
                             and DICTVALUE._needsgc()),
    }
    if getattr(ll_eq_function, 'no_direct_compare', False):
        entrymeths['no_direct_compare'] = True

    # * the key
    entryfields.append(("key", DICTKEY))

    # * the state of the entry - trying to encode it as dummy objects
    if dummykeyobj:
        # all the state can be encoded in the key
        entrymeths['dummy_obj'] = dummykeyobj
        entrymeths['valid'] = ll_valid_from_key
        entrymeths['mark_deleted'] = ll_mark_deleted_in_key
        # the key is overwritten by 'dummy' when the entry is deleted
        entrymeths['must_clear_key'] = False

    elif dummyvalueobj:
        # all the state can be encoded in the value
        entrymeths['dummy_obj'] = dummyvalueobj
        entrymeths['valid'] = ll_valid_from_value
        entrymeths['mark_deleted'] = ll_mark_deleted_in_value
        # value is overwritten by 'dummy' when entry is deleted
        entrymeths['must_clear_value'] = False

    else:
        # we need a flag to know if the entry was ever used
        entryfields.append(("f_valid", lltype.Bool))
        entrymeths['valid'] = ll_valid_from_flag
        entrymeths['mark_deleted'] = ll_mark_deleted_in_flag

    # * the value
    entryfields.append(("value", DICTVALUE))

    if ll_fasthash_function is None:
        entryfields.append(("f_hash", lltype.Signed))
        entrymeths['hash'] = ll_hash_from_cache
    else:
        entrymeths['hash'] = ll_hash_recomputed
        entrymeths['fasthashfn'] = ll_fasthash_function

    # Build the lltype data structures
    DICTENTRY = lltype.Struct("odictentry", *entryfields)
    DICTENTRYARRAY = lltype.GcArray(DICTENTRY, adtmeths=entrymeths)
    fields = [("num_live_items", lltype.Signed),
              ("num_ever_used_items", lltype.Signed),
              ("resize_counter", lltype.Signed), ("indexes", llmemory.GCREF),
              ("lookup_function_no", lltype.Signed),
              ("entries", lltype.Ptr(DICTENTRYARRAY))]
    if get_custom_eq_hash is not None:
        r_rdict_eqfn, r_rdict_hashfn = get_custom_eq_hash()
        fields.extend([("fnkeyeq", r_rdict_eqfn.lowleveltype),
                       ("fnkeyhash", r_rdict_hashfn.lowleveltype)])
        adtmeths = {
            'keyhash': ll_keyhash_custom,
            'keyeq': ll_keyeq_custom,
            'r_rdict_eqfn': r_rdict_eqfn,
            'r_rdict_hashfn': r_rdict_hashfn,
            'paranoia': True,
        }
    else:
        # figure out which functions must be used to hash and compare
        ll_keyhash = ll_hash_function
        ll_keyeq = ll_eq_function
        ll_keyhash = lltype.staticAdtMethod(ll_keyhash)
        if ll_keyeq is not None:
            ll_keyeq = lltype.staticAdtMethod(ll_keyeq)
        adtmeths = {
            'keyhash': ll_keyhash,
            'keyeq': ll_keyeq,
            'paranoia': False,
        }
    adtmeths['KEY'] = DICTKEY
    adtmeths['VALUE'] = DICTVALUE
    adtmeths['lookup_function'] = lltype.staticAdtMethod(
        ll_call_lookup_function)
    adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict)

    DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields))
    return DICT