Пример #1
0
#
#  See documentation in pypy/doc/discussion/rawrefcount.rst
#
#  This is meant for pypy's cpyext module, but is a generally
#  useful interface over our GC.  XXX "pypy" should be removed here
#
import sys, weakref
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.rlib.objectmodel import we_are_translated, specialize
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rlib import rgc

REFCNT_FROM_PYPY = sys.maxint // 4 + 1
REFCNT_FROM_PYPY_LIGHT = REFCNT_FROM_PYPY + (sys.maxint // 2 + 1)

RAWREFCOUNT_DEALLOC_TRIGGER = lltype.Ptr(lltype.FuncType([], lltype.Void))


def _build_pypy_link(p):
    res = len(_adr2pypy)
    _adr2pypy.append(p)
    return res


def init(dealloc_trigger_callback=None):
    """NOT_RPYTHON: set up rawrefcount with the GC.  This is only used
    for tests; it should not be called at all during translation.
    """
    global _p_list, _o_list, _adr2pypy, _pypy2ob
    global _d_list, _dealloc_trigger_callback
    _p_list = []
Пример #2
0
def test_llhelper(monkeypatch):
    """Show how to get function pointers used in type slots"""
    FT = lltype.FuncType([], lltype.Signed)
    FTPTR = lltype.Ptr(FT)

    def make_wrapper(space, func):
        def wrapper():
            return func(space)
        return wrapper
    monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper)

    @specialize.memo()
    def get_tp_function(space, typedef):
        @cpython_api([], lltype.Signed, error=-1, external=False)
        def slot_tp_function(space):
            return typedef.value

        api_func = slot_tp_function.api_func
        return lambda: llhelper(api_func.functype, api_func.get_wrapper(space))

    class Space:
        _cache = {}
        @specialize.memo()
        def fromcache(self, key):
            try:
                return self._cache[key]
            except KeyError:
                result = self._cache[key] = self.build(key)
                return result
        def _freeze_(self):
            return True
    class TypeDef:
        def __init__(self, value):
            self.value = value
        def _freeze_(self):
            return True
    class W_Type:
        def __init__(self, typedef):
            self.instancetypedef = typedef
        def _freeze(self):
            try:
                del self.funcptr
            except AttributeError:
                pass
            return False

    w_type1 = W_Type(TypeDef(123))
    w_type2 = W_Type(TypeDef(456))
    space = Space()

    def run(x):
        if x:
            w_type = w_type1
        else:
            w_type = w_type2
        typedef = w_type.instancetypedef
        w_type.funcptr = get_tp_function(space, typedef)()
        return w_type.funcptr()

    fn = compile(run, [bool])
    assert fn(True) == 123
    assert fn(False) == 456
Пример #3
0
class BaseTestRegalloc(object):
    cpu = CPU(None, None)
    cpu.setup_once()

    def raising_func(i):
        if i:
            raise LLException(zero_division_error, zero_division_value)

    FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
    raising_fptr = llhelper(FPTR, raising_func)
    zero_division_tp, zero_division_value = get_zero_division_error(cpu)
    zd_addr = cpu.cast_int_to_adr(zero_division_tp)
    zero_division_error = llmemory.cast_adr_to_ptr(
        zd_addr, lltype.Ptr(rclass.OBJECT_VTABLE))
    raising_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
                                        EffectInfo.MOST_GENERAL)

    targettoken = TargetToken()
    targettoken2 = TargetToken()
    fdescr1 = BasicFailDescr(1)
    fdescr2 = BasicFailDescr(2)
    fdescr3 = BasicFailDescr(3)

    def setup_method(self, meth):
        self.targettoken._ll_loop_code = 0
        self.targettoken2._ll_loop_code = 0

    def f1(x):
        return x + 1

    def f2(x, y):
        return x * y

    def f10(*args):
        assert len(args) == 10
        return sum(args)

    def fgcref(x):
        return 17

    def fppii(x, y, i, j):
        return 19

    def ff(x, y):
        return x + y + 0.1

    F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
    F2PTR = lltype.Ptr(lltype.FuncType([lltype.Signed] * 2, lltype.Signed))
    F10PTR = lltype.Ptr(lltype.FuncType([lltype.Signed] * 10, lltype.Signed))
    FGCREFPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF], lltype.Signed))
    FPPIIPTR = lltype.Ptr(
        lltype.FuncType(
            [llmemory.GCREF, llmemory.GCREF, lltype.Signed, lltype.Signed],
            lltype.Signed))
    FFPTR = lltype.Ptr(lltype.FuncType([lltype.Float] * 2, lltype.Float))

    f1ptr = llhelper(F1PTR, f1)
    f2ptr = llhelper(F2PTR, f2)
    f10ptr = llhelper(F10PTR, f10)
    fgcrefptr = llhelper(FGCREFPTR, fgcref)
    fppiiptr = llhelper(FPPIIPTR, fppii)
    ffptr = llhelper(FFPTR, ff)

    f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT,
                                   EffectInfo.MOST_GENERAL)
    f2_calldescr = cpu.calldescrof(F2PTR.TO, F2PTR.TO.ARGS, F2PTR.TO.RESULT,
                                   EffectInfo.MOST_GENERAL)
    f10_calldescr = cpu.calldescrof(F10PTR.TO, F10PTR.TO.ARGS,
                                    F10PTR.TO.RESULT, EffectInfo.MOST_GENERAL)
    fgcref_calldescr = cpu.calldescrof(FGCREFPTR.TO, FGCREFPTR.TO.ARGS,
                                       FGCREFPTR.TO.RESULT,
                                       EffectInfo.MOST_GENERAL)
    fppii_calldescr = cpu.calldescrof(FPPIIPTR.TO, FPPIIPTR.TO.ARGS,
                                      FPPIIPTR.TO.RESULT,
                                      EffectInfo.MOST_GENERAL)
    ff_calldescr = cpu.calldescrof(FFPTR.TO, FFPTR.TO.ARGS, FFPTR.TO.RESULT,
                                   EffectInfo.MOST_GENERAL)

    namespace = locals().copy()

    def parse(self, s, boxkinds=None, namespace=None):
        return parse(s,
                     self.cpu,
                     namespace or self.namespace,
                     boxkinds=boxkinds)

    def interpret(self, ops, args, run=True, namespace=None):
        loop = self.parse(ops, namespace=namespace)
        self.loop = loop
        looptoken = JitCellToken()
        self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
        arguments = []
        for arg in args:
            if isinstance(arg, int):
                arguments.append(arg)
            elif isinstance(arg, float):
                arg = longlong.getfloatstorage(arg)
                arguments.append(arg)
            else:
                assert isinstance(lltype.typeOf(arg), lltype.Ptr)
                llgcref = lltype.cast_opaque_ptr(llmemory.GCREF, arg)
                arguments.append(llgcref)
        loop._jitcelltoken = looptoken
        if run:
            self.deadframe = self.cpu.execute_token(looptoken, *arguments)
        return loop

    def prepare_loop(self, ops):
        loop = self.parse(ops)
        self.loop = loop
        regalloc = self.cpu.build_regalloc()
        regalloc.prepare_loop(loop.inputargs, loop.operations,
                              loop.original_jitcell_token, [])
        return regalloc

    def getint(self, index):
        return self.cpu.get_int_value(self.deadframe, index)

    def getfloat(self, index):
        return self.cpu.get_float_value(self.deadframe, index)

    def getints(self, end):
        return [
            self.cpu.get_int_value(self.deadframe, index)
            for index in range(0, end)
        ]

    def getfloats(self, end):
        return [
            longlong.getrealfloat(
                self.cpu.get_float_value(self.deadframe, index))
            for index in range(0, end)
        ]

    def getptr(self, index, T):
        gcref = self.cpu.get_ref_value(self.deadframe, index)
        return lltype.cast_opaque_ptr(T, gcref)

    def attach_bridge(self, ops, loop, guard_op_index, **kwds):
        guard_op = loop.operations[guard_op_index]
        assert guard_op.is_guard()
        bridge = self.parse(ops, **kwds)
        assert ([box.type for box in bridge.inputargs
                 ] == [box.type for box in guard_op.getfailargs()])
        faildescr = guard_op.getdescr()
        self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations,
                                loop._jitcelltoken)
        return bridge

    def run(self, loop, *arguments):
        self.deadframe = self.cpu.execute_token(loop._jitcelltoken, *arguments)
        return self.cpu.get_latest_descr(self.deadframe)
Пример #4
0
 def _transform_hint_close_stack(self, fnptr):
     # We cannot easily pass variable amount of arguments of the call
     # across the call to the pypy_asm_stackwalk helper.  So we store
     # them away and restore them.  More precisely, we need to
     # replace 'graph' with code that saves the arguments, and make
     # a new graph that starts with restoring the arguments.
     if self._asmgcc_save_restore_arguments is None:
         self._asmgcc_save_restore_arguments = {}
     sradict = self._asmgcc_save_restore_arguments
     sra = []  # list of pointers to raw-malloced containers for args
     seen = {}
     FUNC1 = lltype.typeOf(fnptr).TO
     for TYPE in FUNC1.ARGS:
         if isinstance(TYPE, lltype.Ptr):
             TYPE = llmemory.Address
         num = seen.get(TYPE, 0)
         seen[TYPE] = num + 1
         key = (TYPE, num)
         if key not in sradict:
             CONTAINER = lltype.FixedSizeArray(TYPE, 1)
             p = lltype.malloc(CONTAINER,
                               flavor='raw',
                               zero=True,
                               immortal=True)
             sradict[key] = Constant(p, lltype.Ptr(CONTAINER))
         sra.append(sradict[key])
     #
     # make a copy of the graph that will reload the values
     graph = fnptr._obj.graph
     graph2 = copygraph(graph)
     #
     # edit the original graph to only store the value of the arguments
     block = Block(graph.startblock.inputargs)
     c_item0 = Constant('item0', lltype.Void)
     assert len(block.inputargs) == len(sra)
     for v_arg, c_p in zip(block.inputargs, sra):
         if isinstance(v_arg.concretetype, lltype.Ptr):
             v_adr = varoftype(llmemory.Address)
             block.operations.append(
                 SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr))
             v_arg = v_adr
         v_void = varoftype(lltype.Void)
         block.operations.append(
             SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void))
     #
     # call asm_stackwalk(graph2)
     FUNC2 = lltype.FuncType([], FUNC1.RESULT)
     fnptr2 = lltype.functionptr(FUNC2,
                                 fnptr._obj._name + '_reload',
                                 graph=graph2)
     c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2))
     HELPERFUNC = lltype.FuncType(
         [lltype.Ptr(FUNC2), ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT)
     v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk")
     block.operations.append(
         SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk))
     v_result = varoftype(FUNC1.RESULT)
     block.operations.append(
         SpaceOperation("indirect_call", [
             v_asm_stackwalk, c_fnptr2, c_gcrootanchor,
             Constant(None, lltype.Void)
         ], v_result))
     block.closeblock(Link([v_result], graph.returnblock))
     graph.startblock = block
     #
     # edit the copy of the graph to reload the values
     block2 = graph2.startblock
     block1 = Block([])
     reloadedvars = []
     for v, c_p in zip(block2.inputargs, sra):
         v = v.copy()
         if isinstance(v.concretetype, lltype.Ptr):
             w = varoftype(llmemory.Address)
         else:
             w = v
         block1.operations.append(
             SpaceOperation('getfield', [c_p, c_item0], w))
         if w is not v:
             block1.operations.append(
                 SpaceOperation('cast_adr_to_ptr', [w], v))
         reloadedvars.append(v)
     block1.closeblock(Link(reloadedvars, block2))
     graph2.startblock = block1
     #
     checkgraph(graph)
     checkgraph(graph2)
Пример #5
0
#
#   - %rbx, %r12, %r13, %r14, %r15, %rbp; and the frame address
#

if IS_64_BITS:
    CALLEE_SAVED_REGS = 6
    INDEX_OF_EBP = 5
    FRAME_PTR = CALLEE_SAVED_REGS
else:
    CALLEE_SAVED_REGS = 4  # there are 4 callee-saved registers
    INDEX_OF_EBP = 3
    FRAME_PTR = CALLEE_SAVED_REGS  # the frame is at index 4 in the array

JIT_USE_WORDS = 2 + FRAME_PTR + 1

ASM_CALLBACK_PTR = lltype.Ptr(lltype.FuncType([], lltype.Void))

# used internally by walk_stack_from()
WALKFRAME = lltype.Struct(
    'WALKFRAME',
    (
        'regs_stored_at',  # address of where the registers have been saved
        lltype.FixedSizeArray(llmemory.Address, CALLEE_SAVED_REGS)),
    ('frame_address', llmemory.Address),
)

# We have a circular doubly-linked list of all the ASM_FRAMEDATAs currently
# alive.  The list's starting point is given by 'gcrootanchor', which is not
# a full ASM_FRAMEDATA but only contains the prev/next pointers:
ASM_FRAMEDATA_HEAD_PTR = lltype.Ptr(lltype.ForwardReference())
ASM_FRAMEDATA_HEAD_PTR.TO.become(
Пример #6
0
                ll_buf[i] = chr(arg & 0xFF)
                arg >>= 8
        elif _BIG_ENDIAN:
            for i in range(c_size - 1, -1, -1):
                ll_buf[i] = chr(arg & 0xFF)
                arg >>= 8
        else:
            raise AssertionError


push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)'

# type defs for callback and closure userdata
USERDATA_P = lltype.Ptr(lltype.ForwardReference())
CALLBACK_TP = lltype.Ptr(
    lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P], lltype.Void))
USERDATA_P.TO.become(
    lltype.Struct('userdata', ('callback', CALLBACK_TP),
                  ('addarg', lltype.Signed),
                  hints={'callback': True}))


@jit.jit_callback("CLIBFFI")
def _ll_callback(ffi_cif, ll_res, ll_args, ll_userdata):
    """ Callback specification.
    ffi_cif - something ffi specific, don't care
    ll_args - rffi.VOIDPP - pointer to array of pointers to args
    ll_restype - rffi.VOIDP - pointer to result
    ll_userdata - a special structure which holds necessary information
                  (what the real callback is for example), casted to VOIDP
    """
Пример #7
0
def llhelper_args(f, ARGS, RESULT):
    return llhelper(lltype.Ptr(lltype.FuncType(ARGS, RESULT)), f)