Exemplo n.º 1
0
def indirect_residual_call_test(argtypes, restype, expectedkind):
    # an indirect call that is residual in all cases is very similar to
    # a residual direct call
    op = get_direct_call_op(argtypes, restype)
    op.opname = "indirect_call"
    op.args[0] = varoftype(op.args[0].concretetype)
    op.args.append(Constant(["somegraph1", "somegraph2"], lltype.Void))
    tr = Transformer(FakeCPU(), FakeResidualIndirectCallControl())
    tr.graph = "someinitialgraph"
    oplist = tr.rewrite_operation(op)
    op0, op1 = oplist
    reskind = getkind(restype)[0]
    assert op0.opname == "residual_call_%s_%s" % (expectedkind, reskind)
    assert op0.result == op.result
    assert op0.args[0] == op.args[0]
    assert op0.args[-1] == "calldescr"
    assert len(op0.args) == 1 + len(expectedkind) + 1
    for sublist, kind1 in zip(op0.args[1:-1], expectedkind):
        assert sublist.kind.startswith(kind1)
        assert list(sublist) == [v for v in op.args[1:] if getkind(v.concretetype) == sublist.kind]
    for v in op.args[1:]:
        kind = getkind(v.concretetype)
        assert kind == "void" or kind[0] in expectedkind
    assert op1.opname == "-live-"
    assert op1.args == []
Exemplo n.º 2
0
 def calldescrof(self, FUNC, ARGS, RESULT, effect_info):
     key = ('call', getkind(RESULT), tuple([getkind(A)
                                            for A in ARGS]), effect_info)
     try:
         return self.descrs[key]
     except KeyError:
         descr = CallDescr(RESULT, ARGS, effect_info)
         self.descrs[key] = descr
         return descr
Exemplo n.º 3
0
 def calldescrof(self, FUNC, ARGS, RESULT, effect_info):
     key = ('call', getkind(RESULT),
            tuple([getkind(A) for A in ARGS]),
            effect_info)
     try:
         return self.descrs[key]
     except KeyError:
         descr = CallDescr(RESULT, ARGS, effect_info)
         self.descrs[key] = descr
         return descr
Exemplo n.º 4
0
 def make_args_specification(self, jd):
     graph = jd._jit_merge_point_in
     _, _, op = locate_jit_merge_point(graph)
     greens_v, reds_v = support.decode_hp_hint_args(op)
     ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
     jd._green_args_spec = [v.concretetype for v in greens_v]
     jd.red_args_types = [history.getkind(v.concretetype) for v in reds_v]
     jd.num_green_args = len(jd._green_args_spec)
     jd.num_red_args = len(jd.red_args_types)
     RESTYPE = graph.getreturnvar().concretetype
     (jd._JIT_ENTER_FUNCTYPE,
      jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(
          ALLARGS, lltype.Void)
     (jd._PORTAL_FUNCTYPE,
      jd._PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE)
     #
     if jd.result_type == 'v':
         ASMRESTYPE = lltype.Void
     elif jd.result_type == history.INT:
         ASMRESTYPE = lltype.Signed
     elif jd.result_type == history.REF:
         ASMRESTYPE = llmemory.GCREF
     elif jd.result_type == history.FLOAT:
         ASMRESTYPE = lltype.Float
     else:
         assert False
     (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType(
         [llmemory.GCREF, llmemory.GCREF], ASMRESTYPE)
Exemplo n.º 5
0
 def split_graph_and_record_jitdriver(self, graph, block, pos):
     op = block.operations[pos]
     jd = JitDriverStaticData()
     jd._jit_merge_point_in = graph
     args = op.args[2:]
     s_binding = self.translator.annotator.binding
     jd._portal_args_s = [s_binding(v) for v in args]
     graph = copygraph(graph)
     [jmpp] = find_jit_merge_points([graph])
     graph.startblock = support.split_before_jit_merge_point(*jmpp)
     # XXX this is incredibly obscure, but this is sometiems necessary
     #     so we don't explode in checkgraph. for reasons unknown this
     #     is not contanied within simplify_graph
     removenoops.remove_same_as(graph)
     # a crash in the following checkgraph() means that you forgot
     # to list some variable in greens=[] or reds=[] in JitDriver,
     # or that a jit_merge_point() takes a constant as an argument.
     checkgraph(graph)
     for v in graph.getargs():
         assert isinstance(v, Variable)
     assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs())
     self.translator.graphs.append(graph)
     jd.portal_graph = graph
     # it's a bit unbelievable to have a portal without func
     assert hasattr(graph, "func")
     graph.func._dont_inline_ = True
     graph.func._jit_unroll_safe_ = True
     jd.jitdriver = block.operations[pos].args[1].value
     jd.portal_runner_ptr = "<not set so far>"
     jd.result_type = history.getkind(jd.portal_graph.getreturnvar()
                                      .concretetype)[0]
     self.jitdrivers_sd.append(jd)
Exemplo n.º 6
0
 def split_graph_and_record_jitdriver(self, graph, block, pos):
     op = block.operations[pos]
     jd = JitDriverStaticData()
     jd._jit_merge_point_in = graph
     args = op.args[2:]
     s_binding = self.translator.annotator.binding
     jd._portal_args_s = [s_binding(v) for v in args]
     graph = copygraph(graph)
     [jmpp] = find_jit_merge_points([graph])
     graph.startblock = support.split_before_jit_merge_point(*jmpp)
     # XXX this is incredibly obscure, but this is sometiems necessary
     #     so we don't explode in checkgraph. for reasons unknown this
     #     is not contanied within simplify_graph
     removenoops.remove_same_as(graph)
     # a crash in the following checkgraph() means that you forgot
     # to list some variable in greens=[] or reds=[] in JitDriver,
     # or that a jit_merge_point() takes a constant as an argument.
     checkgraph(graph)
     for v in graph.getargs():
         assert isinstance(v, Variable)
     assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs())
     self.translator.graphs.append(graph)
     jd.portal_graph = graph
     # it's a bit unbelievable to have a portal without func
     assert hasattr(graph, "func")
     graph.func._dont_inline_ = True
     graph.func._jit_unroll_safe_ = True
     jd.jitdriver = block.operations[pos].args[1].value
     jd.portal_runner_ptr = "<not set so far>"
     jd.result_type = history.getkind(
         jd.portal_graph.getreturnvar().concretetype)[0]
     self.jitdrivers_sd.append(jd)
Exemplo n.º 7
0
 def make_args_specification(self, jd):
     graph = jd._jit_merge_point_in
     _, _, op = locate_jit_merge_point(graph)
     greens_v, reds_v = support.decode_hp_hint_args(op)
     ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
     jd._green_args_spec = [v.concretetype for v in greens_v]
     jd.red_args_types = [history.getkind(v.concretetype) for v in reds_v]
     jd.num_green_args = len(jd._green_args_spec)
     jd.num_red_args = len(jd.red_args_types)
     RESTYPE = graph.getreturnvar().concretetype
     (jd._JIT_ENTER_FUNCTYPE,
      jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
     (jd._PORTAL_FUNCTYPE,
      jd._PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE)
     #
     if jd.result_type == 'v':
         ASMRESTYPE = lltype.Void
     elif jd.result_type == history.INT:
         ASMRESTYPE = lltype.Signed
     elif jd.result_type == history.REF:
         ASMRESTYPE = llmemory.GCREF
     elif jd.result_type == history.FLOAT:
         ASMRESTYPE = lltype.Float
     else:
         assert False
     (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType(
         [llmemory.GCREF, llmemory.GCREF], ASMRESTYPE)
Exemplo n.º 8
0
    def __init__(self, TYPE):
        DescrWithKey.__init__(self, TYPE)
        from rpython.jit.backend.llgraph.runner import boxresult
        from rpython.jit.metainterp.warmstate import unwrap
        ARRAY = ootype.Array(TYPE)

        def create():
            if isinstance(TYPE, ootype.OOType):
                return boxresult(TYPE, ootype.new(TYPE))
            return None

        def create_array(lengthbox):
            n = lengthbox.getint()
            return boxresult(ARRAY, ootype.oonewarray(ARRAY, n))

        def getarrayitem(arraybox, ibox):
            array = arraybox.getref(ARRAY)
            i = ibox.getint()
            if TYPE is not ootype.Void:
                return boxresult(TYPE, array.ll_getitem_fast(i))

        def setarrayitem(arraybox, ibox, valuebox):
            array = arraybox.getref(ARRAY)
            i = ibox.getint()
            value = unwrap(TYPE, valuebox)
            array.ll_setitem_fast(i, value)

        def getarraylength(arraybox):
            array = arraybox.getref(ARRAY)
            return boxresult(ootype.Signed, array.ll_length())

        def instanceof(box):
            if isinstance(TYPE, ootype.Instance):
                obj = box.getref(ootype.ROOT)
                return BoxInt(ootype.instanceof(obj, TYPE))
            return None

        self.create = create
        self.create_array = create_array
        self.getarrayitem = getarrayitem
        self.setarrayitem = setarrayitem
        self.getarraylength = getarraylength
        self.instanceof = instanceof
        self.ooclass = get_class_for_type(TYPE)
        self.typename = TYPE._short_name()
        self._is_array_of_pointers = (history.getkind(TYPE) == 'ref')
        self._is_array_of_floats = (history.getkind(TYPE) == 'float')
Exemplo n.º 9
0
 def serialize_op(self, op):
     args = self.flatten_list(op.args)
     if op.result is not None:
         kind = getkind(op.result.concretetype)
         if kind != 'void':
             args.append("->")
             args.append(self.getcolor(op.result))
     self.emitline(op.opname, *args)
Exemplo n.º 10
0
 def serialize_op(self, op):
     args = self.flatten_list(op.args)
     if op.result is not None:
         kind = getkind(op.result.concretetype)
         if kind != 'void':
             args.append("->")
             args.append(self.getcolor(op.result))
     self.emitline(op.opname, *args)
Exemplo n.º 11
0
def cast_arg(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_from_int(TP, x)
    elif kind == 'ref':
        return cast_from_ptr(TP, x)
    else:
        assert kind == 'float'
        return cast_from_floatstorage(TP, x)
Exemplo n.º 12
0
def cast_arg(TP, x):
    kind = getkind(TP)
    if kind == "int":
        return cast_from_int(TP, x)
    elif kind == "ref":
        return cast_from_ptr(TP, x)
    else:
        assert kind == "float"
        return cast_from_floatstorage(TP, x)
Exemplo n.º 13
0
    def make_execute_token(self, *ARGS):
        """Build and return a function for executing the given JIT token.

        Each chunk of compiled code is represented by an integer "function id".
        We need to look up the id, build the necessary frame, and then call the
        helper function "jitInvoke" to execute the compiled function.
        """
        #  This is mostly copied from llsupport/llmodel.py, but with changes
        #  to invoke the external javascript helper thingy.
        lst = [(i, history.getkind(ARG)[0]) for i, ARG in enumerate(ARGS)]
        kinds = unrolling_iterable(lst)

        def execute_token(executable_token, *args):
            clt = executable_token.compiled_loop_token
            assert isinstance(clt, CompiledLoopTokenASMJS)
            funcid = clt.func.compiled_funcid
            loopid = clt.compiled_loopid
            frame_info = clt.func.frame_info
            frame = self.gc_ll_descr.malloc_jitframe(frame_info)
            ll_frame = lltype.cast_opaque_ptr(llmemory.GCREF, frame)
            locs = clt._ll_initial_locs
            if SANITYCHECK:
                assert len(locs) == len(args)
            if not self.translate_support_code:
                prev_interpreter = LLInterpreter.current_interpreter
                LLInterpreter.current_interpreter = self.debug_ll_interpreter
            try:
                # Store each argument into the frame.
                for i, kind in kinds:
                    arg = args[i]
                    num = locs[i]
                    if kind == history.INT:
                        self.set_int_value(ll_frame, num, arg)
                    elif kind == history.FLOAT:
                        self.set_float_value(ll_frame, num, arg)
                    else:
                        assert kind == history.REF
                        self.set_ref_value(ll_frame, num, arg)
                llop.gc_writebarrier(lltype.Void, ll_frame)
                # Send the threadlocaladdr.
                if self.translate_support_code:
                    ll_tlref = llop.threadlocalref_addr(llmemory.Address)
                else:
                    ll_tlref = rffi.cast(llmemory.Address,
                                         self._debug_errno_container)
                # Invoke it via the helper.
                ll_frameadr = self.cast_ptr_to_int(ll_frame)
                ll_tladdr = self.cast_adr_to_int(ll_tlref)
                ll_frameadr = support.jitInvoke(funcid, ll_frameadr, ll_tladdr,
                                                loopid)
                ll_frame = self.cast_int_to_ptr(ll_frameadr, llmemory.GCREF)
            finally:
                if not self.translate_support_code:
                    LLInterpreter.current_interpreter = prev_interpreter
            return ll_frame

        return execute_token
Exemplo n.º 14
0
def cast_arg(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_from_int(TP, x)
    elif kind == 'ref':
        return cast_from_ptr(TP, x)
    else:
        assert kind == 'float'
        return cast_from_floatstorage(TP, x)
Exemplo n.º 15
0
    def make_execute_token(self, *ARGS):
        """Build and return a function for executing the given JIT token.

        Each chunk of compiled code is represented by an integer "function id".
        We need to look up the id, build the necessary frame, and then call the
        helper function "jitInvoke" to execute the compiled function.
        """
        #  This is mostly copied from llsupport/llmodel.py, but with changes
        #  to invoke the external javascript helper thingy.
        lst = [(i, history.getkind(ARG)[0]) for i, ARG in enumerate(ARGS)]
        kinds = unrolling_iterable(lst)

        def execute_token(executable_token, *args):
            clt = executable_token.compiled_loop_token
            assert isinstance(clt, CompiledLoopTokenASMJS)
            funcid = clt.func.compiled_funcid
            loopid = clt.compiled_loopid
            frame_info = clt.func.frame_info
            frame = self.gc_ll_descr.malloc_jitframe(frame_info)
            ll_frame = lltype.cast_opaque_ptr(llmemory.GCREF, frame)
            locs = clt._ll_initial_locs
            if SANITYCHECK:
                assert len(locs) == len(args)
            if not self.translate_support_code:
                prev_interpreter = LLInterpreter.current_interpreter
                LLInterpreter.current_interpreter = self.debug_ll_interpreter
            try:
                # Store each argument into the frame.
                for i, kind in kinds:
                    arg = args[i]
                    num = locs[i]
                    if kind == history.INT:
                        self.set_int_value(ll_frame, num, arg)
                    elif kind == history.FLOAT:
                        self.set_float_value(ll_frame, num, arg)
                    else:
                        assert kind == history.REF
                        self.set_ref_value(ll_frame, num, arg)
                llop.gc_writebarrier(lltype.Void, ll_frame)
                # Send the threadlocaladdr.
                if self.translate_support_code:
                    ll_tlref = llop.threadlocalref_addr(
                        llmemory.Address)
                else:
                    ll_tlref = rffi.cast(llmemory.Address,
                        self._debug_errno_container)
                # Invoke it via the helper.
                ll_frameadr = self.cast_ptr_to_int(ll_frame)
                ll_tladdr = self.cast_adr_to_int(ll_tlref)
                ll_frameadr = support.jitInvoke(funcid, ll_frameadr, ll_tladdr, loopid)
                ll_frame = self.cast_int_to_ptr(ll_frameadr, llmemory.GCREF)
            finally:
                if not self.translate_support_code:
                    LLInterpreter.current_interpreter = prev_interpreter
            return ll_frame

        return execute_token
Exemplo n.º 16
0
    def make_execute_token(self, *ARGS):
        # The JIT backend must generate functions with the following
        # signature: it takes the jitframe and the threadlocal_addr
        # as arguments, and it returns the (possibly reallocated) jitframe.
        # The backend can optimize OS_THREADLOCALREF_GET calls to return a
        # field of this threadlocal_addr, but only if 'translate_support_code':
        # in untranslated tests, threadlocal_addr is a dummy container
        # for errno tests only.
        FUNCPTR = lltype.Ptr(
            lltype.FuncType([llmemory.GCREF, llmemory.Address],
                            llmemory.GCREF))

        lst = [(i, history.getkind(ARG)[0]) for i, ARG in enumerate(ARGS)]
        kinds = unrolling_iterable(lst)

        def execute_token(executable_token, *args):
            clt = executable_token.compiled_loop_token
            assert len(args) == clt._debug_nbargs
            #
            addr = executable_token._ll_function_addr
            func = rffi.cast(FUNCPTR, addr)
            #llop.debug_print(lltype.Void, ">>>> Entering", addr)
            frame_info = clt.frame_info
            frame = self.gc_ll_descr.malloc_jitframe(frame_info)
            ll_frame = lltype.cast_opaque_ptr(llmemory.GCREF, frame)
            locs = executable_token.compiled_loop_token._ll_initial_locs
            prev_interpreter = None  # help flow space
            if not self.translate_support_code:
                prev_interpreter = LLInterpreter.current_interpreter
                LLInterpreter.current_interpreter = self.debug_ll_interpreter
            try:
                for i, kind in kinds:
                    arg = args[i]
                    num = locs[i]
                    if kind == history.INT:
                        self.set_int_value(ll_frame, num, arg)
                    elif kind == history.FLOAT:
                        self.set_float_value(ll_frame, num, arg)
                    else:
                        assert kind == history.REF
                        self.set_ref_value(ll_frame, num, arg)
                if self.translate_support_code:
                    ll_threadlocal_addr = llop.threadlocalref_addr(
                        llmemory.Address)
                else:
                    ll_threadlocal_addr = rffi.cast(
                        llmemory.Address, self._debug_errno_container)
                llop.gc_writebarrier(lltype.Void, ll_frame)
                ll_frame = func(ll_frame, ll_threadlocal_addr)
            finally:
                if not self.translate_support_code:
                    LLInterpreter.current_interpreter = prev_interpreter
            #llop.debug_print(lltype.Void, "<<<< Back")
            return ll_frame

        return execute_token
Exemplo n.º 17
0
 def getcolor(self, v):
     if isinstance(v, Constant):
         return v
     kind = getkind(v.concretetype)
     col = self.regallocs[kind].getcolor(v)    # if kind=='void', fix caller
     try:
         r = self.registers[kind, col]
     except KeyError:
         r = self.registers[kind, col] = Register(kind, col)
     return r
Exemplo n.º 18
0
 def getcolor(self, v):
     if isinstance(v, Constant):
         return v
     kind = getkind(v.concretetype)
     col = self.regallocs[kind].getcolor(v)  # if kind=='void', fix caller
     try:
         r = self.registers[kind, col]
     except KeyError:
         r = self.registers[kind, col] = Register(kind, col)
     return r
Exemplo n.º 19
0
def residual_call_test(argtypes, restype, expectedkind):
    op = get_direct_call_op(argtypes, restype)
    tr = Transformer(FakeCPU(), FakeResidualCallControl())
    oplist = tr.rewrite_operation(op)
    op0, op1 = oplist
    reskind = getkind(restype)[0]
    assert op0.opname == "residual_call_%s_%s" % (expectedkind, reskind)
    assert op0.result == op.result
    assert op0.args[0] == op.args[0]
    assert op0.args[-1] == "calldescr"
    assert len(op0.args) == 1 + len(expectedkind) + 1
    for sublist, kind1 in zip(op0.args[1:-1], expectedkind):
        assert sublist.kind.startswith(kind1)
        assert list(sublist) == [v for v in op.args[1:] if getkind(v.concretetype) == sublist.kind]
    for v in op.args[1:]:
        kind = getkind(v.concretetype)
        assert kind == "void" or kind[0] in expectedkind
    assert op1.opname == "-live-"
    assert op1.args == []
Exemplo n.º 20
0
def direct_call_test(argtypes, restype, expectedkind):
    op = get_direct_call_op(argtypes, restype)
    tr = Transformer(FakeCPU(), FakeRegularCallControl())
    tr.graph = "someinitialgraph"
    oplist = tr.rewrite_operation(op)
    op0, op1 = oplist
    reskind = getkind(restype)[0]
    assert op0.opname == "inline_call_%s_%s" % (expectedkind, reskind)
    assert op0.result == op.result
    assert op0.args[0] == "somejitcode"
    assert len(op0.args) == 1 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[1:], expectedkind):
        assert sublist.kind.startswith(kind1)
        assert list(sublist) == [v for v in op.args[1:] if getkind(v.concretetype) == sublist.kind]
    for v in op.args[1:]:
        kind = getkind(v.concretetype)
        assert kind == "void" or kind[0] in expectedkind
    assert op1.opname == "-live-"
    assert op1.args == []
Exemplo n.º 21
0
    def make_execute_token(self, *ARGS):
        # The JIT backend must generate functions with the following
        # signature: it takes the jitframe and the threadlocal_addr
        # as arguments, and it returns the (possibly reallocated) jitframe.
        # The backend can optimize OS_THREADLOCALREF_GET calls to return a
        # field of this threadlocal_addr, but only if 'translate_support_code':
        # in untranslated tests, threadlocal_addr is a dummy container
        # for errno tests only.
        FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, llmemory.Address],
                                             llmemory.GCREF))

        lst = [(i, history.getkind(ARG)[0]) for i, ARG in enumerate(ARGS)]
        kinds = unrolling_iterable(lst)

        def execute_token(executable_token, *args):
            clt = executable_token.compiled_loop_token
            assert len(args) == clt._debug_nbargs
            #
            addr = executable_token._ll_function_addr
            func = rffi.cast(FUNCPTR, addr)
            #llop.debug_print(lltype.Void, ">>>> Entering", addr)
            frame_info = clt.frame_info
            frame = self.gc_ll_descr.malloc_jitframe(frame_info)
            ll_frame = lltype.cast_opaque_ptr(llmemory.GCREF, frame)
            locs = executable_token.compiled_loop_token._ll_initial_locs
            prev_interpreter = None   # help flow space
            if not self.translate_support_code:
                prev_interpreter = LLInterpreter.current_interpreter
                LLInterpreter.current_interpreter = self.debug_ll_interpreter
            try:
                for i, kind in kinds:
                    arg = args[i]
                    num = locs[i]
                    if kind == history.INT:
                        self.set_int_value(ll_frame, num, arg)
                    elif kind == history.FLOAT:
                        self.set_float_value(ll_frame, num, arg)
                    else:
                        assert kind == history.REF
                        self.set_ref_value(ll_frame, num, arg)
                if self.translate_support_code:
                    ll_threadlocal_addr = llop.threadlocalref_addr(
                        llmemory.Address)
                else:
                    ll_threadlocal_addr = rffi.cast(llmemory.Address,
                        self._debug_errno_container)
                llop.gc_writebarrier(lltype.Void, ll_frame)
                ll_frame = func(ll_frame, ll_threadlocal_addr)
            finally:
                if not self.translate_support_code:
                    LLInterpreter.current_interpreter = prev_interpreter
            #llop.debug_print(lltype.Void, "<<<< Back")
            return ll_frame
        return execute_token
Exemplo n.º 22
0
def cast_result(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_to_int(x)
    elif kind == 'ref':
        return cast_to_ptr(x)
    elif kind == 'float':
        return cast_to_floatstorage(x)
    else:
        assert kind == 'void'
        assert x is None
        return None
Exemplo n.º 23
0
def map_type_to_argclass(ARG, accept_void=False):
    kind = getkind(ARG)
    if kind == 'int':
        if ARG is lltype.SingleFloat: return 'S'
        else: return 'i'
    elif kind == 'ref': return 'r'
    elif kind == 'float':
        if is_longlong(ARG): return 'L'
        else: return 'f'
    elif kind == 'void':
        if accept_void: return 'v'
    raise NotImplementedError('ARG = %r' % (ARG, ))
Exemplo n.º 24
0
def map_type_to_argclass(ARG, accept_void=False):
    kind = getkind(ARG)
    if   kind == 'int':
        if ARG is lltype.SingleFloat: return 'S'
        else:                         return 'i'
    elif kind == 'ref':               return 'r'
    elif kind == 'float':
        if is_longlong(ARG):          return 'L'
        else:                         return 'f'
    elif kind == 'void':
        if accept_void:               return 'v'
    raise NotImplementedError('ARG = %r' % (ARG,))
Exemplo n.º 25
0
def cast_result(TP, x):
    kind = getkind(TP)
    if kind == 'int':
        return cast_to_int(x)
    elif kind == 'ref':
        return cast_to_ptr(x)
    elif kind == 'float':
        return cast_to_floatstorage(x)
    else:
        assert kind == 'void'
        assert x is None
        return None
Exemplo n.º 26
0
def cast_result(TP, x):
    kind = getkind(TP)
    if kind == "int":
        return cast_to_int(x)
    elif kind == "ref":
        return cast_to_ptr(x)
    elif kind == "float":
        return cast_to_floatstorage(x)
    else:
        assert kind == "void"
        assert x is None
        return None
Exemplo n.º 27
0
Arquivo: runner.py Projeto: sota/pypy
 def __init__(self, TYPE, fieldname):
     DescrWithKey.__init__(self, (TYPE, fieldname))
     from rpython.jit.backend.llgraph.runner import boxresult
     from rpython.jit.metainterp.warmstate import unwrap
     _, T = TYPE._lookup_field(fieldname)
     def getfield(objbox):
         obj = objbox.getref(TYPE)
         value = getattr(obj, fieldname)
         return boxresult(T, value)
     def setfield(objbox, valuebox):
         obj = objbox.getref(TYPE)
         value = unwrap(T, valuebox)
         setattr(obj, fieldname, value)
         
     self.getfield = getfield
     self.setfield = setfield
     self.selfclass = ootype.runtimeClass(TYPE)
     self.fieldname = fieldname
     self.key = key_manager.getkey((TYPE, fieldname))
     self._is_pointer_field = (history.getkind(T) == 'ref')
     self._is_float_field = (history.getkind(T) == 'float')
Exemplo n.º 28
0
Arquivo: runner.py Projeto: sota/pypy
 def __init__(self, TYPE):
     DescrWithKey.__init__(self, TYPE)
     from rpython.jit.backend.llgraph.runner import boxresult
     from rpython.jit.metainterp.warmstate import unwrap
     ARRAY = ootype.Array(TYPE)
     def create():
         if isinstance(TYPE, ootype.OOType):
             return boxresult(TYPE, ootype.new(TYPE))
         return None
     def create_array(lengthbox):
         n = lengthbox.getint()
         return boxresult(ARRAY, ootype.oonewarray(ARRAY, n))
     def getarrayitem(arraybox, ibox):
         array = arraybox.getref(ARRAY)
         i = ibox.getint()
         if TYPE is not ootype.Void:
             return boxresult(TYPE, array.ll_getitem_fast(i))
     def setarrayitem(arraybox, ibox, valuebox):
         array = arraybox.getref(ARRAY)
         i = ibox.getint()
         value = unwrap(TYPE, valuebox)
         array.ll_setitem_fast(i, value)
     def getarraylength(arraybox):
         array = arraybox.getref(ARRAY)
         return boxresult(ootype.Signed, array.ll_length())
     def instanceof(box):
         if isinstance(TYPE, ootype.Instance):
             obj = box.getref(ootype.ROOT)
             return BoxInt(ootype.instanceof(obj, TYPE))
         return None
     self.create = create
     self.create_array = create_array
     self.getarrayitem = getarrayitem
     self.setarrayitem = setarrayitem
     self.getarraylength = getarraylength
     self.instanceof = instanceof
     self.ooclass = get_class_for_type(TYPE)
     self.typename = TYPE._short_name()
     self._is_array_of_pointers = (history.getkind(TYPE) == 'ref')
     self._is_array_of_floats = (history.getkind(TYPE) == 'float')
Exemplo n.º 29
0
 def enforce_input_args(self):
     inputargs = self.graph.startblock.inputargs
     numkinds = {}
     for v in inputargs:
         kind = getkind(v.concretetype)
         if kind == 'void':
             continue
         curcol = self.regallocs[kind].getcolor(v)
         realcol = numkinds.get(kind, 0)
         numkinds[kind] = realcol + 1
         if curcol != realcol:
             assert curcol > realcol
             self.regallocs[kind].swapcolors(realcol, curcol)
Exemplo n.º 30
0
 def enforce_input_args(self):
     inputargs = self.graph.startblock.inputargs
     numkinds = {}
     for v in inputargs:
         kind = getkind(v.concretetype)
         if kind == 'void':
             continue
         curcol = self.regallocs[kind].getcolor(v)
         realcol = numkinds.get(kind, 0)
         numkinds[kind] = realcol + 1
         if curcol != realcol:
             assert curcol > realcol
             self.regallocs[kind].swapcolors(realcol, curcol)
Exemplo n.º 31
0
def indirect_regular_call_test(argtypes, restype, expectedkind):
    # a regular indirect call is preceded by a guard_value on the
    # function address, so that pyjitpl can know which jitcode to follow
    from rpython.jit.codewriter.flatten import IndirectCallTargets

    op = get_direct_call_op(argtypes, restype)
    op.opname = "indirect_call"
    op.args[0] = varoftype(op.args[0].concretetype)
    op.args.append(Constant(["somegraph1", "somegraph2"], lltype.Void))
    tr = Transformer(FakeCPU(), FakeRegularIndirectCallControl())
    tr.graph = "someinitialgraph"
    oplist = tr.rewrite_operation(op)
    op0gv, op1gv, op0, op1 = oplist
    assert op0gv.opname == "-live-"
    assert op0gv.args == []
    assert op1gv.opname == "int_guard_value"
    assert op1gv.args == [op.args[0]]
    assert op1gv.result is None
    #
    reskind = getkind(restype)[0]
    assert op0.opname == "residual_call_%s_%s" % (expectedkind, reskind)
    assert op0.result == op.result
    assert op0.args[0] == op.args[0]
    assert isinstance(op0.args[1], IndirectCallTargets)
    assert op0.args[1].lst == ["somejitcode1", "somejitcode2"]
    assert op0.args[-1] == "calldescr"
    assert len(op0.args) == 2 + len(expectedkind) + 1
    for sublist, kind1 in zip(op0.args[2:-1], expectedkind):
        assert sublist.kind.startswith(kind1)
        assert list(sublist) == [v for v in op.args[1:] if getkind(v.concretetype) == sublist.kind]
    for v in op.args[1:]:
        kind = getkind(v.concretetype)
        assert kind == "void" or kind[0] in expectedkind
    # Note: we still expect a -live- here, even though canraise() returns
    # False, because this 'residual_call' will likely call further jitcodes
    # which can do e.g. guard_class or other stuff requiring anyway a -live-.
    assert op1.opname == "-live-"
    assert op1.args == []
Exemplo n.º 32
0
 def execute_call(self, calldescr, func, *args):
     effectinfo = calldescr.get_extra_info()
     if effectinfo is not None and hasattr(effectinfo, 'oopspecindex'):
         oopspecindex = effectinfo.oopspecindex
         if oopspecindex == EffectInfo.OS_MATH_SQRT:
             return self._do_math_sqrt(args[0])
     TP = llmemory.cast_int_to_adr(func).ptr._obj._TYPE
     call_args = support.cast_call_args_in_order(TP.ARGS, args)
     try:
         res = self.cpu.maybe_on_top_of_llinterp(func, call_args, TP.RESULT)
         self.last_exception = None
     except LLException, lle:
         self.last_exception = lle
         res = _example_res[getkind(TP.RESULT)[0]]
Exemplo n.º 33
0
    def __init__(self, TYPE, fieldname):
        DescrWithKey.__init__(self, (TYPE, fieldname))
        from rpython.jit.backend.llgraph.runner import boxresult
        from rpython.jit.metainterp.warmstate import unwrap
        _, T = TYPE._lookup_field(fieldname)

        def getfield(objbox):
            obj = objbox.getref(TYPE)
            value = getattr(obj, fieldname)
            return boxresult(T, value)

        def setfield(objbox, valuebox):
            obj = objbox.getref(TYPE)
            value = unwrap(T, valuebox)
            setattr(obj, fieldname, value)

        self.getfield = getfield
        self.setfield = setfield
        self.selfclass = ootype.runtimeClass(TYPE)
        self.fieldname = fieldname
        self.key = key_manager.getkey((TYPE, fieldname))
        self._is_pointer_field = (history.getkind(T) == 'ref')
        self._is_float_field = (history.getkind(T) == 'float')
Exemplo n.º 34
0
 def execute_call(self, calldescr, func, *args):
     effectinfo = calldescr.get_extra_info()
     if effectinfo is not None and hasattr(effectinfo, 'oopspecindex'):
         oopspecindex = effectinfo.oopspecindex
         if oopspecindex == EffectInfo.OS_MATH_SQRT:
             return self._do_math_sqrt(args[0])
     TP = llmemory.cast_int_to_adr(func).ptr._obj._TYPE
     call_args = support.cast_call_args_in_order(TP.ARGS, args)
     try:
         res = self.cpu.maybe_on_top_of_llinterp(func, call_args, TP.RESULT)
         self.last_exception = None
     except LLException, lle:
         self.last_exception = lle
         res = _example_res[getkind(TP.RESULT)[0]]
Exemplo n.º 35
0
 def str_storage_getitem(self, TYPE, buf, offset):
     def f():
         return str_storage_getitem(TYPE, buf, offset)
     res = self.interp_operations(f, [], supports_singlefloats=True)
     #
     kind = getkind(TYPE)[0] # 'i' or 'f'
     self.check_operations_history({'gc_load_indexed_%s' % kind: 1,
                                    'finish': 1})
     #
     if TYPE == lltype.SingleFloat:
         # interp_operations returns the int version of r_singlefloat, but
         # our tests expects to receive an r_singlefloat: let's convert it
         # back!
         return longlong.int2singlefloat(res)
     return res
Exemplo n.º 36
0
 def make_return(self, args):
     if len(args) == 1:
         # return from function
         [v] = args
         kind = getkind(v.concretetype)
         if kind == 'void':
             self.emitline("void_return")
         else:
             self.emitline("%s_return" % kind, self.getcolor(args[0]))
     elif len(args) == 2:
         # exception block, raising an exception from a function
         if isinstance(args[1], Variable):
             self.emitline("-live-")     # xxx hack
         self.emitline("raise", self.getcolor(args[1]))
     else:
         raise Exception("?")
     self.emitline("---")
Exemplo n.º 37
0
 def make_return(self, args):
     if len(args) == 1:
         # return from function
         [v] = args
         kind = getkind(v.concretetype)
         if kind == 'void':
             self.emitline("void_return")
         else:
             self.emitline("%s_return" % kind, self.getcolor(args[0]))
     elif len(args) == 2:
         # exception block, raising an exception from a function
         if isinstance(args[1], Variable):
             self.emitline("-live-")  # xxx hack
         self.emitline("raise", self.getcolor(args[1]))
     else:
         raise Exception("?")
     self.emitline("---")
Exemplo n.º 38
0
    def gc_load_from_string(self, TYPE, buf, offset):
        def f(offset):
            return str_gc_load(TYPE, buf, offset)

        res = self.interp_operations(f, [offset], supports_singlefloats=True)
        #
        kind = getkind(TYPE)[0]  # 'i' or 'f'
        self.check_operations_history({
            'gc_load_indexed_%s' % kind: 1,
            'finish': 1
        })
        #
        if TYPE == lltype.SingleFloat:
            # interp_operations returns the int version of r_singlefloat, but
            # our tests expects to receive an r_singlefloat: let's convert it
            # back!
            return longlong.int2singlefloat(res)
        return res
Exemplo n.º 39
0
 def field_descr(self, builder, r):
     v, S = builder.get_structptr_var(r, )
     names = S._names
     if names[0] == 'parent':
         names = names[1:]
     choice = []
     kind = optypes[self.opnum]
     for name in names:
         FIELD = getattr(S, name)
         if not isinstance(FIELD, lltype.Ptr):
             if kind == 'n' or getkind(FIELD)[0] == kind:
                 choice.append(name)
     if not choice:
         raise test_random.CannotProduceOperation
     name = r.choice(choice)
     descr = builder.cpu.fielddescrof(S, name)
     descr._random_info = 'cpu.fielddescrof(..., %r)' % (name,)
     descr._random_type = S
     TYPE = getattr(S, name)
     return v, descr, TYPE
Exemplo n.º 40
0
 def field_descr(self, builder, r):
     v, S = builder.get_structptr_var(r, )
     names = S._names
     if names[0] == 'parent':
         names = names[1:]
     choice = []
     kind = optypes[self.opnum]
     for name in names:
         FIELD = getattr(S, name)
         if not isinstance(FIELD, lltype.Ptr):
             if kind == 'n' or getkind(FIELD)[0] == kind:
                 choice.append(name)
     if not choice:
         raise test_random.CannotProduceOperation
     name = r.choice(choice)
     descr = builder.cpu.fielddescrof(S, name)
     descr._random_info = 'cpu.fielddescrof(..., %r)' % (name, )
     descr._random_type = S
     TYPE = getattr(S, name)
     return v, descr, TYPE
Exemplo n.º 41
0
def cast_call_args_in_order(ARGS, args):
    call_args = []
    i = 0
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == "int":
            n = cast_from_int(ARG, args[i])
            i += 1
        elif kind == "ref":
            n = cast_from_ptr(ARG, args[i])
            i += 1
        elif kind == "float":
            n = cast_from_floatstorage(ARG, args[i])
            i += 1
        elif kind == "void":
            n = None
        else:
            raise AssertionError(kind)
        call_args.append(n)
    assert i == len(args)
    return call_args
Exemplo n.º 42
0
def cast_call_args_in_order(ARGS, args):
    call_args = []
    i = 0
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == 'int':
            n = cast_from_int(ARG, args[i])
            i += 1
        elif kind == 'ref':
            n = cast_from_ptr(ARG, args[i])
            i += 1
        elif kind == 'float':
            n = cast_from_floatstorage(ARG, args[i])
            i += 1
        elif kind == 'void':
            n = None
        else:
            raise AssertionError(kind)
        call_args.append(n)
    assert i == len(args)
    return call_args
Exemplo n.º 43
0
def sort_vars(args_v):
    from rpython.jit.metainterp.history import getkind
    _kind2count = {'int': 1, 'ref': 2, 'float': 3}
    return sorted(args_v, key=lambda v: _kind2count[getkind(v.concretetype)])
Exemplo n.º 44
0
 def get_arg_types(self):
     return ''.join([getkind(ARG)[0] for ARG in self.ARGS])
Exemplo n.º 45
0
def _get_jitcodes(testself,
                  CPUClass,
                  func,
                  values,
                  supports_floats=True,
                  supports_longlong=False,
                  supports_singlefloats=False,
                  translationoptions={},
                  **kwds):
    from rpython.jit.codewriter import support

    class FakeJitCell(object):
        __product_token = None

        def get_procedure_token(self):
            return self.__product_token

        def set_procedure_token(self, token):
            self.__product_token = token

    class FakeWarmRunnerState(object):
        def attach_procedure_to_interp(self, greenkey, procedure_token):
            assert greenkey == []
            self._cell.set_procedure_token(procedure_token)

        def helper_func(self, FUNCPTR, func):
            from rpython.rtyper.annlowlevel import llhelper
            return llhelper(FUNCPTR, func)

        def get_unique_id(self, *args):
            return 0

        def get_location_str(self, args):
            return 'location'

        class JitCell:
            @staticmethod
            def get_jit_cell_at_key(greenkey):
                assert greenkey == []
                return FakeWarmRunnerState._cell

        _cell = FakeJitCell()

        trace_limit = sys.maxint
        enable_opts = ALL_OPTS_DICT
        vec = True

    if kwds.pop('disable_optimizations', False):
        FakeWarmRunnerState.enable_opts = {}

    func._jit_unroll_safe_ = True
    rtyper = support.annotate(func,
                              values,
                              translationoptions=translationoptions)
    graphs = rtyper.annotator.translator.graphs
    testself.all_graphs = graphs
    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]

    class FakeJitDriverSD:
        num_green_args = 0
        portal_graph = graphs[0]
        virtualizable_info = None
        greenfield_info = None
        result_type = result_kind
        portal_runner_ptr = "???"
        vec = False

    stats = history.Stats(None)
    cpu = CPUClass(rtyper, stats, None, False)
    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
    cw.debug = True
    testself.cw = cw
    if supports_floats and not cpu.supports_floats:
        py.test.skip("this test requires supports_floats=True")
    if supports_longlong and not cpu.supports_longlong:
        py.test.skip("this test requires supports_longlong=True")
    if supports_singlefloats and not cpu.supports_singlefloats:
        py.test.skip("this test requires supports_singlefloats=True")
    policy = JitPolicy()
    policy.set_supports_floats(supports_floats)
    policy.set_supports_longlong(supports_longlong)
    policy.set_supports_singlefloats(supports_singlefloats)
    graphs = cw.find_all_graphs(policy)
    if kwds.get("backendopt"):
        backend_optimizations(rtyper.annotator.translator, graphs=graphs)
    #
    testself.warmrunnerstate = FakeWarmRunnerState()
    testself.warmrunnerstate.cpu = cpu
    FakeJitDriverSD.warmstate = testself.warmrunnerstate
    if hasattr(testself, 'finish_setup_for_interp_operations'):
        testself.finish_setup_for_interp_operations()
    #
    cw.make_jitcodes(verbose=True)
    return stats
Exemplo n.º 46
0
    def rewrite_jit_merge_point(self, jd, policy):
        #
        # Mutate the original portal graph from this:
        #
        #       def original_portal(..):
        #           stuff
        #           while 1:
        #               jit_merge_point(*args)
        #               more stuff
        #
        # to that:
        #
        #       def original_portal(..):
        #           stuff
        #           return portal_runner(*args)
        #
        #       def portal_runner(*args):
        #           while 1:
        #               try:
        #                   return portal(*args)
        #               except ContinueRunningNormally, e:
        #                   *args = *e.new_args
        #               except DoneWithThisFrame, e:
        #                   return e.return
        #               except ExitFrameWithException, e:
        #                   raise Exception, e.value
        #
        #       def portal(*args):
        #           while 1:
        #               more stuff
        #
        origportalgraph = jd._jit_merge_point_in
        portalgraph = jd.portal_graph
        PORTALFUNC = jd._PORTAL_FUNCTYPE

        # ____________________________________________________________
        # Prepare the portal_runner() helper
        #
        from rpython.jit.metainterp.warmstate import specialize_value
        from rpython.jit.metainterp.warmstate import unspecialize_value
        portal_ptr = self.cpu.ts.functionptr(PORTALFUNC,
                                             'portal',
                                             graph=portalgraph)
        jd._portal_ptr = portal_ptr
        #
        portalfunc_ARGS = []
        nums = {}
        for i, ARG in enumerate(PORTALFUNC.ARGS):
            kind = history.getkind(ARG)
            assert kind != 'void'
            if i < len(jd.jitdriver.greens):
                color = 'green'
            else:
                color = 'red'
            attrname = '%s_%s' % (color, kind)
            count = nums.get(attrname, 0)
            nums[attrname] = count + 1
            portalfunc_ARGS.append((ARG, attrname, count))
        portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS)
        #
        rtyper = self.translator.rtyper
        RESULT = PORTALFUNC.RESULT
        result_kind = history.getkind(RESULT)
        ts = self.cpu.ts
        state = jd.warmstate
        maybe_compile_and_run = jd._maybe_compile_and_run_fn

        def ll_portal_runner(*args):
            start = True
            while 1:
                try:
                    # maybe enter from the function's start.  Note that the
                    # 'start' variable is constant-folded away because it's
                    # the first statement in the loop.
                    if start:
                        maybe_compile_and_run(
                            state.increment_function_threshold, *args)
                    #
                    # then run the normal portal function, i.e. the
                    # interpreter's main loop.  It might enter the jit
                    # via maybe_enter_jit(), which typically ends with
                    # handle_fail() being called, which raises on the
                    # following exceptions --- catched here, because we
                    # want to interrupt the whole interpreter loop.
                    return support.maybe_on_top_of_llinterp(
                        rtyper, portal_ptr)(*args)
                except jitexc.ContinueRunningNormally, e:
                    args = ()
                    for ARGTYPE, attrname, count in portalfunc_ARGS:
                        x = getattr(e, attrname)[count]
                        x = specialize_value(ARGTYPE, x)
                        args = args + (x, )
                    start = False
                    continue
                except jitexc.DoneWithThisFrameVoid:
                    assert result_kind == 'void'
                    return
                except jitexc.DoneWithThisFrameInt, e:
                    assert result_kind == 'int'
                    return specialize_value(RESULT, e.result)
Exemplo n.º 47
0
 def get_result_type(self):
     return getkind(self.RESULT)[0]
Exemplo n.º 48
0
    def rewrite_jit_merge_point(self, jd, policy):
        #
        # Mutate the original portal graph from this:
        #
        #       def original_portal(..):
        #           stuff
        #           while 1:
        #               jit_merge_point(*args)
        #               more stuff
        #
        # to that:
        #
        #       def original_portal(..):
        #           stuff
        #           return portal_runner(*args)
        #
        #       def portal_runner(*args):
        #           while 1:
        #               try:
        #                   return portal(*args)
        #               except JitException, e:
        #                   return handle_jitexception(e)
        #
        #       def portal(*args):
        #           while 1:
        #               more stuff
        #
        origportalgraph = jd._jit_merge_point_in
        portalgraph = jd.portal_graph
        PORTALFUNC = jd._PORTAL_FUNCTYPE

        # ____________________________________________________________
        # Prepare the portal_runner() helper
        #
        from rpython.jit.metainterp.warmstate import specialize_value
        from rpython.jit.metainterp.warmstate import unspecialize_value
        portal_ptr = self.cpu.ts.functionptr(PORTALFUNC,
                                             'portal',
                                             graph=portalgraph)
        jd._portal_ptr = portal_ptr
        #
        portalfunc_ARGS = []
        nums = {}
        for i, ARG in enumerate(PORTALFUNC.ARGS):
            kind = history.getkind(ARG)
            assert kind != 'void'
            if i < len(jd.jitdriver.greens):
                color = 'green'
            else:
                color = 'red'
            attrname = '%s_%s' % (color, kind)
            count = nums.get(attrname, 0)
            nums[attrname] = count + 1
            portalfunc_ARGS.append((ARG, attrname, count))
        portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS)
        #
        rtyper = self.translator.rtyper
        RESULT = PORTALFUNC.RESULT
        result_kind = history.getkind(RESULT)
        assert result_kind.startswith(jd.result_type)
        ts = self.cpu.ts
        state = jd.warmstate
        maybe_compile_and_run = jd._maybe_compile_and_run_fn
        EnterJitAssembler = jd._EnterJitAssembler

        def ll_portal_runner(*args):
            try:
                # maybe enter from the function's start.
                maybe_compile_and_run(state.increment_function_threshold,
                                      *args)
                #
                # then run the normal portal function, i.e. the
                # interpreter's main loop.  It might enter the jit
                # via maybe_enter_jit(), which typically ends with
                # handle_fail() being called, which raises on the
                # following exceptions --- catched here, because we
                # want to interrupt the whole interpreter loop.
                return support.maybe_on_top_of_llinterp(rtyper,
                                                        portal_ptr)(*args)
            except jitexc.JitException as e:
                result = handle_jitexception(e)
                if result_kind != 'void':
                    result = specialize_value(RESULT, result)
                return result

        def handle_jitexception(e):
            # XXX there are too many exceptions all around...
            while True:
                if isinstance(e, EnterJitAssembler):
                    try:
                        return e.execute()
                    except jitexc.JitException as e:
                        continue
                #
                if isinstance(e, jitexc.ContinueRunningNormally):
                    args = ()
                    for ARGTYPE, attrname, count in portalfunc_ARGS:
                        x = getattr(e, attrname)[count]
                        x = specialize_value(ARGTYPE, x)
                        args = args + (x, )
                    try:
                        result = support.maybe_on_top_of_llinterp(
                            rtyper, portal_ptr)(*args)
                    except jitexc.JitException as e:
                        continue
                    if result_kind != 'void':
                        result = unspecialize_value(result)
                    return result
                #
                if result_kind == 'void':
                    if isinstance(e, jitexc.DoneWithThisFrameVoid):
                        return None
                if result_kind == 'int':
                    if isinstance(e, jitexc.DoneWithThisFrameInt):
                        return e.result
                if result_kind == 'ref':
                    if isinstance(e, jitexc.DoneWithThisFrameRef):
                        return e.result
                if result_kind == 'float':
                    if isinstance(e, jitexc.DoneWithThisFrameFloat):
                        return e.result
                #
                if isinstance(e, jitexc.ExitFrameWithExceptionRef):
                    value = ts.cast_to_baseclass(e.value)
                    if not we_are_translated():
                        raise LLException(ts.get_typeptr(value), value)
                    else:
                        value = cast_base_ptr_to_instance(Exception, value)
                        assert value is not None
                        raise value
                #
                raise AssertionError("all cases should have been handled")

        jd._ll_portal_runner = ll_portal_runner  # for debugging
        jd.portal_runner_ptr = self.helper_func(jd._PTR_PORTAL_FUNCTYPE,
                                                ll_portal_runner)
        jd.portal_runner_adr = llmemory.cast_ptr_to_adr(jd.portal_runner_ptr)
        jd.portal_calldescr = self.cpu.calldescrof(
            jd._PTR_PORTAL_FUNCTYPE.TO, jd._PTR_PORTAL_FUNCTYPE.TO.ARGS,
            jd._PTR_PORTAL_FUNCTYPE.TO.RESULT, EffectInfo.MOST_GENERAL)

        vinfo = jd.virtualizable_info

        def assembler_call_helper(deadframe, virtualizableref):
            fail_descr = self.cpu.get_latest_descr(deadframe)
            try:
                fail_descr.handle_fail(deadframe, self.metainterp_sd, jd)
            except jitexc.JitException as e:
                return handle_jitexception(e)
            else:
                assert 0, "should have raised"

        jd._assembler_call_helper = assembler_call_helper  # for debugging
        jd._assembler_helper_ptr = self.helper_func(
            jd._PTR_ASSEMBLER_HELPER_FUNCTYPE, assembler_call_helper)
        jd.assembler_helper_adr = llmemory.cast_ptr_to_adr(
            jd._assembler_helper_ptr)
        if vinfo is not None:
            jd.vable_token_descr = vinfo.vable_token_descr

        def handle_jitexception_from_blackhole(bhcaller, e):
            result = handle_jitexception(e)
            if result_kind == 'void':
                pass
            elif result_kind == 'int':
                bhcaller._setup_return_value_i(result)
            elif result_kind == 'ref':
                bhcaller._setup_return_value_r(result)
            elif result_kind == 'float':
                bhcaller._setup_return_value_f(result)
            else:
                assert False

        jd.handle_jitexc_from_bh = handle_jitexception_from_blackhole

        # ____________________________________________________________
        # Now mutate origportalgraph to end with a call to portal_runner_ptr
        #
        origblock, origindex, op = locate_jit_merge_point(origportalgraph)
        assert op.opname == 'jit_marker'
        assert op.args[0].value == 'jit_merge_point'
        greens_v, reds_v = support.decode_hp_hint_args(op)
        vlist = [Constant(jd.portal_runner_ptr, jd._PTR_PORTAL_FUNCTYPE)]
        vlist += greens_v
        vlist += reds_v
        v_result = Variable()
        v_result.concretetype = PORTALFUNC.RESULT
        newop = SpaceOperation('direct_call', vlist, v_result)
        del origblock.operations[origindex:]
        origblock.operations.append(newop)
        origblock.exitswitch = None
        origblock.recloseblock(Link([v_result], origportalgraph.returnblock))
        # the origportal now can raise (even if it did not raise before),
        # which means that we cannot inline it anywhere any more, but that's
        # fine since any forced inlining has been done before
        #
        checkgraph(origportalgraph)
Exemplo n.º 49
0
 def get_arg_types(self):
     return ''.join([getkind(ARG)[0] for ARG in self.ARGS])
Exemplo n.º 50
0
    def __init__(self, warmrunnerdesc, VTYPEPTR):
        self.warmrunnerdesc = warmrunnerdesc
        cpu = warmrunnerdesc.cpu
        self.cpu = cpu
        #
        VTYPEPTR1 = VTYPEPTR
        while 'virtualizable_accessor' not in deref(VTYPEPTR)._hints:
            VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR)
            assert VTYPEPTR is not None, (
                "%r is listed in the jit driver's 'virtualizables', "
                "but that class doesn't have a '_virtualizable_' attribute "
                "(if it has _virtualizable2_, rename it to _virtualizable_)" %
                (VTYPEPTR1, ))
        self.VTYPEPTR = VTYPEPTR
        self.VTYPE = VTYPE = deref(VTYPEPTR)
        self.vable_token_descr = cpu.fielddescrof(VTYPE, 'vable_token')
        #
        accessor = VTYPE._hints['virtualizable_accessor']
        all_fields = accessor.fields
        static_fields = []
        array_fields = []
        for name, tp in all_fields.iteritems():
            if tp == IR_IMMUTABLE_ARRAY:
                array_fields.append(name)
            elif tp == IR_IMMUTABLE:
                static_fields.append(name)
            else:
                raise Exception("unknown type: %s" % tp)
        self.static_fields = static_fields
        self.array_fields = array_fields
        #
        FIELDTYPES = [fieldType(VTYPE, name) for name in static_fields]
        ARRAYITEMTYPES = []
        for name in array_fields:
            ARRAYPTR = fieldType(VTYPE, name)
            ARRAY = deref(ARRAYPTR)
            assert isinstance(ARRAYPTR, lltype.Ptr)
            if not isinstance(ARRAY, lltype.GcArray):
                raise Exception(
                    "The virtualizable field '%s' is not an array (found %r)."
                    " It usually means that you must try harder to ensure that"
                    " the list is not resized at run-time. You can do that by"
                    " using rpython.rlib.debug.make_sure_not_resized()." %
                    (name, ARRAY))
            ARRAYITEMTYPES.append(arrayItem(ARRAY))
        self.array_descrs = [
            cpu.arraydescrof(deref(fieldType(VTYPE, name)))
            for name in array_fields
        ]
        #
        self.num_static_extra_boxes = len(static_fields)
        self.num_arrays = len(array_fields)
        self.static_field_to_extra_box = dict([
            (name, i) for (i, name) in enumerate(static_fields)
        ])
        self.array_field_counter = dict([
            (name, i) for (i, name) in enumerate(array_fields)
        ])
        self.static_extra_types = [
            history.getkind(TYPE) for TYPE in FIELDTYPES
        ]
        self.arrayitem_extra_types = [
            history.getkind(ITEM) for ITEM in ARRAYITEMTYPES
        ]
        self.static_field_descrs = [
            cpu.fielddescrof(VTYPE, name) for name in static_fields
        ]
        self.array_field_descrs = [
            cpu.fielddescrof(VTYPE, name) for name in array_fields
        ]

        for descr in self.static_field_descrs:
            descr.vinfo = self
        for descr in self.array_field_descrs:
            descr.vinfo = self

        self.static_field_by_descrs = dict([
            (descr, i) for (i, descr) in enumerate(self.static_field_descrs)
        ])
        self.array_field_by_descrs = dict([
            (descr, i) for (i, descr) in enumerate(self.array_field_descrs)
        ])
        #
        getlength = cpu.ts.getlength
        getarrayitem = cpu.ts.getarrayitem
        setarrayitem = cpu.ts.setarrayitem

        def read_boxes(cpu, virtualizable):
            assert lltype.typeOf(virtualizable) == llmemory.GCREF
            virtualizable = cast_gcref_to_vtype(virtualizable)
            boxes = []
            for _, fieldname in unroll_static_fields:
                x = getattr(virtualizable, fieldname)
                boxes.append(wrap(cpu, x))
            for _, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                for i in range(getlength(lst)):
                    boxes.append(wrap(cpu, getarrayitem(lst, i)))
            return boxes

        def write_boxes(virtualizable, boxes):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            i = 0
            for FIELDTYPE, fieldname in unroll_static_fields:
                x = unwrap(FIELDTYPE, boxes[i])
                setattr(virtualizable, fieldname, x)
                i = i + 1
            for ARRAYITEMTYPE, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                for j in range(getlength(lst)):
                    x = unwrap(ARRAYITEMTYPE, boxes[i])
                    setarrayitem(lst, j, x)
                    i = i + 1
            assert len(boxes) == i + 1

        def get_total_size(virtualizable):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            size = 0
            for _, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                size += getlength(lst)
            for _, fieldname in unroll_static_fields:
                size += 1
            return size

        def write_from_resume_data_partial(virtualizable, reader):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            # Load values from the reader (see resume.py) described by
            # the list of numbers 'nums', and write them in their proper
            # place in the 'virtualizable'.
            for FIELDTYPE, fieldname in unroll_static_fields:
                x = reader.load_next_value_of_type(FIELDTYPE)
                setattr(virtualizable, fieldname, x)
            for ARRAYITEMTYPE, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                for j in range(getlength(lst)):
                    x = reader.load_next_value_of_type(ARRAYITEMTYPE)
                    setarrayitem(lst, j, x)

        def load_list_of_boxes(virtualizable, reader, vable_box):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            # Uses 'virtualizable' only to know the length of the arrays;
            # does not write anything into it.  The returned list is in
            # the format expected of virtualizable_boxes, so it ends in
            # the virtualizable itself.
            boxes = []
            for FIELDTYPE, fieldname in unroll_static_fields:
                box = reader.next_box_of_type(FIELDTYPE)
                boxes.append(box)
            for ARRAYITEMTYPE, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                for j in range(getlength(lst)):
                    box = reader.next_box_of_type(ARRAYITEMTYPE)
                    boxes.append(box)
            boxes.append(vable_box)
            return boxes

        def check_boxes(virtualizable, boxes):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            # for debugging
            i = 0
            for FIELDTYPE, fieldname in unroll_static_fields:
                x = unwrap(FIELDTYPE, boxes[i])
                assert getattr(virtualizable, fieldname) == x
                i = i + 1
            for ARRAYITEMTYPE, fieldname in unroll_array_fields:
                lst = getattr(virtualizable, fieldname)
                for j in range(getlength(lst)):
                    x = unwrap(ARRAYITEMTYPE, boxes[i])
                    assert getarrayitem(lst, j) == x
                    i = i + 1
            assert len(boxes) == i + 1

        def get_index_in_array(virtualizable, arrayindex, index):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            index += self.num_static_extra_boxes
            j = 0
            for _, fieldname in unroll_array_fields:
                if arrayindex == j:
                    return index
                lst = getattr(virtualizable, fieldname)
                index += getlength(lst)
                j = j + 1
            assert False, "invalid arrayindex"

        def get_array_length(virtualizable, arrayindex):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            j = 0
            for _, fieldname in unroll_array_fields:
                if arrayindex == j:
                    lst = getattr(virtualizable, fieldname)
                    return getlength(lst)
                j += 1
            assert False, "invalid arrayindex"

        unroll_static_fields = unrolling_iterable(
            zip(FIELDTYPES, static_fields))
        unroll_array_fields = unrolling_iterable(
            zip(ARRAYITEMTYPES, array_fields))
        unroll_static_fields_rev = unrolling_iterable(
            reversed(list(unroll_static_fields)))
        unroll_array_fields_rev = unrolling_iterable(
            reversed(list(unroll_array_fields)))
        self.read_boxes = read_boxes
        self.write_boxes = write_boxes
        self.write_from_resume_data_partial = write_from_resume_data_partial
        self.load_list_of_boxes = load_list_of_boxes
        self.check_boxes = check_boxes
        self.get_index_in_array = get_index_in_array
        self.get_array_length = get_array_length
        self.get_total_size = get_total_size

        def cast_to_vtype(virtualizable):
            return self.cpu.ts.cast_to_instance_maybe(VTYPEPTR, virtualizable)

        self.cast_to_vtype = cast_to_vtype

        def cast_gcref_to_vtype(virtualizable):
            assert lltype.typeOf(virtualizable) == llmemory.GCREF
            return lltype.cast_opaque_ptr(VTYPEPTR, virtualizable)

        self.cast_gcref_to_vtype = cast_gcref_to_vtype

        def clear_vable_token(virtualizable):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            if virtualizable.vable_token:
                force_now(virtualizable)
                assert not virtualizable.vable_token

        self.clear_vable_token = clear_vable_token

        def tracing_before_residual_call(virtualizable):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            assert not virtualizable.vable_token
            virtualizable.vable_token = TOKEN_TRACING_RESCALL

        self.tracing_before_residual_call = tracing_before_residual_call

        def tracing_after_residual_call(virtualizable):
            """
            Returns whether or not the virtualizable was forced during a
            CALL_MAY_FORCE.
            """
            virtualizable = cast_gcref_to_vtype(virtualizable)
            if virtualizable.vable_token:
                # not modified by the residual call; assert that it is still
                # set to TOKEN_TRACING_RESCALL and clear it.
                assert virtualizable.vable_token == TOKEN_TRACING_RESCALL
                virtualizable.vable_token = TOKEN_NONE
                return False
            else:
                # marker "modified during residual call" set.
                return True

        self.tracing_after_residual_call = tracing_after_residual_call

        def force_now(virtualizable):
            token = virtualizable.vable_token
            if token == TOKEN_TRACING_RESCALL:
                # The values in the virtualizable are always correct during
                # tracing.  We only need to reset vable_token to TOKEN_NONE
                # as a marker for the tracing, to tell it that this
                # virtualizable escapes.
                virtualizable.vable_token = TOKEN_NONE
            else:
                from rpython.jit.metainterp.compile import ResumeGuardForcedDescr
                ResumeGuardForcedDescr.force_now(cpu, token)
                assert virtualizable.vable_token == TOKEN_NONE

        force_now._dont_inline_ = True
        self.force_now = force_now

        def is_token_nonnull_gcref(virtualizable):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            return bool(virtualizable.vable_token)

        self.is_token_nonnull_gcref = is_token_nonnull_gcref

        def reset_token_gcref(virtualizable):
            virtualizable = cast_gcref_to_vtype(virtualizable)
            virtualizable.vable_token = TOKEN_NONE

        self.reset_token_gcref = reset_token_gcref

        def reset_vable_token(virtualizable):
            virtualizable.vable_token = TOKEN_NONE

        self.reset_vable_token = reset_vable_token
Exemplo n.º 51
0
 def bh_new_array(self, length, arraydescr):
     array = lltype.malloc(arraydescr.A, length, zero=True)
     assert getkind(arraydescr.A.OF) != 'ref'  # getkind crashes on structs
     return lltype.cast_opaque_ptr(llmemory.GCREF, array)
Exemplo n.º 52
0
def perform_register_allocation(graph, kind):
    checkkind = lambda v: getkind(v.concretetype) == kind
    return regalloc.perform_register_allocation(graph, checkkind, ListOfKind)
Exemplo n.º 53
0
 def write_insn(self, insn):
     if insn[0] == '---':
         return
     if isinstance(insn[0], Label):
         self.label_positions[insn[0].name] = len(self.code)
         return
     if insn[0] == '-live-':
         key = len(self.code)
         live_i, live_r, live_f = self.liveness.get(key, ("", "", ""))
         live_i = self.get_liveness_info(live_i, insn[1:], 'int')
         live_r = self.get_liveness_info(live_r, insn[1:], 'ref')
         live_f = self.get_liveness_info(live_f, insn[1:], 'float')
         self.liveness[key] = live_i, live_r, live_f
         return
     startposition = len(self.code)
     self.code.append("temporary placeholder")
     #
     argcodes = []
     allow_short = (insn[0] in USE_C_FORM)
     for x in insn[1:]:
         if isinstance(x, Register):
             self.emit_reg(x)
             argcodes.append(x.kind[0])
         elif isinstance(x, Constant):
             kind = getkind(x.concretetype)
             is_short = self.emit_const(x, kind, allow_short=allow_short)
             if is_short:
                 argcodes.append('c')
             else:
                 argcodes.append(kind[0])
         elif isinstance(x, TLabel):
             self.alllabels.add(len(self.code))
             self.tlabel_positions.append((x.name, len(self.code)))
             self.code.append("temp 1")
             self.code.append("temp 2")
             argcodes.append('L')
         elif isinstance(x, ListOfKind):
             itemkind = x.kind
             lst = list(x)
             assert len(lst) <= 255, "list too long!"
             self.code.append(chr(len(lst)))
             for item in lst:
                 if isinstance(item, Register):
                     assert itemkind == item.kind
                     self.emit_reg(item)
                 elif isinstance(item, Constant):
                     assert itemkind == getkind(item.concretetype)
                     self.emit_const(item, itemkind)
                 else:
                     raise NotImplementedError("found in ListOfKind(): %r"
                                               % (item,))
             argcodes.append(itemkind[0].upper())
         elif isinstance(x, AbstractDescr):
             if x not in self._descr_dict:
                 self._descr_dict[x] = len(self.descrs)
                 self.descrs.append(x)
             if isinstance(x, SwitchDictDescr):
                 self.switchdictdescrs.append(x)
             num = self._descr_dict[x]
             assert 0 <= num <= 0xFFFF, "too many AbstractDescrs!"
             self.code.append(chr(num & 0xFF))
             self.code.append(chr(num >> 8))
             argcodes.append('d')
         elif isinstance(x, IndirectCallTargets):
             self.indirectcalltargets.update(x.lst)
         elif x == '->':
             assert '>' not in argcodes
             argcodes.append('>')
         else:
             raise NotImplementedError(x)
     #
     opname = insn[0]
     if '>' in argcodes:
         assert argcodes.index('>') == len(argcodes) - 2
         self.resulttypes[len(self.code)] = argcodes[-1]
     key = opname + '/' + ''.join(argcodes)
     num = self.insns.setdefault(key, len(self.insns))
     self.code[startposition] = chr(num)
     self.startpoints.add(startposition)
Exemplo n.º 54
0
 def write_insn(self, insn):
     if insn[0] == '---':
         return
     if isinstance(insn[0], Label):
         self.label_positions[insn[0].name] = len(self.code)
         return
     if insn[0] == '-live-':
         key = len(self.code)
         live_i, live_r, live_f = self.liveness.get(key, ("", "", ""))
         live_i = self.get_liveness_info(live_i, insn[1:], 'int')
         live_r = self.get_liveness_info(live_r, insn[1:], 'ref')
         live_f = self.get_liveness_info(live_f, insn[1:], 'float')
         self.liveness[key] = live_i, live_r, live_f
         return
     startposition = len(self.code)
     self.code.append("temporary placeholder")
     #
     argcodes = []
     allow_short = (insn[0] in USE_C_FORM)
     for x in insn[1:]:
         if isinstance(x, Register):
             self.emit_reg(x)
             argcodes.append(x.kind[0])
         elif isinstance(x, Constant):
             kind = getkind(x.concretetype)
             is_short = self.emit_const(x, kind, allow_short=allow_short)
             if is_short:
                 argcodes.append('c')
             else:
                 argcodes.append(kind[0])
         elif isinstance(x, TLabel):
             self.alllabels.add(len(self.code))
             self.tlabel_positions.append((x.name, len(self.code)))
             self.code.append("temp 1")
             self.code.append("temp 2")
             argcodes.append('L')
         elif isinstance(x, ListOfKind):
             itemkind = x.kind
             lst = list(x)
             assert len(lst) <= 255, "list too long!"
             self.code.append(chr(len(lst)))
             for item in lst:
                 if isinstance(item, Register):
                     assert itemkind == item.kind
                     self.emit_reg(item)
                 elif isinstance(item, Constant):
                     assert itemkind == getkind(item.concretetype)
                     self.emit_const(item, itemkind)
                 else:
                     raise NotImplementedError("found in ListOfKind(): %r" %
                                               (item, ))
             argcodes.append(itemkind[0].upper())
         elif isinstance(x, AbstractDescr):
             if x not in self._descr_dict:
                 self._descr_dict[x] = len(self.descrs)
                 self.descrs.append(x)
             if isinstance(x, SwitchDictDescr):
                 self.switchdictdescrs.append(x)
             num = self._descr_dict[x]
             assert 0 <= num <= 0xFFFF, "too many AbstractDescrs!"
             self.code.append(chr(num & 0xFF))
             self.code.append(chr(num >> 8))
             argcodes.append('d')
         elif isinstance(x, IndirectCallTargets):
             self.indirectcalltargets.update(x.lst)
         elif x == '->':
             assert '>' not in argcodes
             argcodes.append('>')
         else:
             raise NotImplementedError(x)
     #
     opname = insn[0]
     if '>' in argcodes:
         assert argcodes.index('>') == len(argcodes) - 2
         self.resulttypes[len(self.code)] = argcodes[-1]
     key = opname + '/' + ''.join(argcodes)
     num = self.insns.setdefault(key, len(self.insns))
     self.code[startposition] = chr(num)
     self.startpoints.add(startposition)
Exemplo n.º 55
0
 def bh_new_array(self, length, arraydescr):
     array = lltype.malloc(arraydescr.A, length, zero=True)
     assert getkind(arraydescr.A.OF) != 'ref' # getkind crashes on structs
     return lltype.cast_opaque_ptr(llmemory.GCREF, array)
Exemplo n.º 56
0
 def get_result_type(self):
     return getkind(self.RESULT)[0]
Exemplo n.º 57
0
 def insert_exits(self, block):
     if len(block.exits) == 1:
         # A single link, fall-through
         link = block.exits[0]
         assert link.exitcase in (None, False, True)
         # the cases False or True should not really occur, but can show
         # up in the manually hacked graphs for generators...
         self.make_link(link)
     #
     elif block.exitswitch is c_last_exception:
         # An exception block. See test_exc_exitswitch in test_flatten.py
         # for an example of what kind of code this makes.
         index = -1
         while True:
             lastopname = block.operations[index].opname
             if lastopname != '-live-':
                 break
             index -= 1
         assert block.exits[0].exitcase is None  # is this always True?
         #
         if not self._include_all_exc_links:
             if index == -1:
                 # cannot raise: the last instruction is not
                 # actually a '-live-'
                 self.make_link(block.exits[0])
                 return
         #
         self.emitline('catch_exception', TLabel(block.exits[0]))
         self.make_link(block.exits[0])
         self.emitline(Label(block.exits[0]))
         for link in block.exits[1:]:
             if (link.exitcase is Exception
                     or (link.exitcase is OverflowError
                         and lastopname.startswith('int_')
                         and lastopname.endswith('_ovf'))):
                 # this link captures all exceptions
                 self.make_exception_link(link)
                 break
             self.emitline(
                 'goto_if_exception_mismatch',
                 Constant(link.llexitcase, lltype.typeOf(link.llexitcase)),
                 TLabel(link))
             self.make_exception_link(link)
             self.emitline(Label(link))
         else:
             # no link captures all exceptions, so we have to put a reraise
             # for the other exceptions
             self.emitline("reraise")
             self.emitline("---")
     #
     elif len(block.exits) == 2 and (isinstance(block.exitswitch, tuple)
                                     or block.exitswitch.concretetype
                                     == lltype.Bool):
         # Two exit links with a boolean condition
         linkfalse, linktrue = block.exits
         if linkfalse.llexitcase == True:
             linkfalse, linktrue = linktrue, linkfalse
         opname = 'goto_if_not'
         livebefore = False
         if isinstance(block.exitswitch, tuple):
             # special case produced by jtransform.optimize_goto_if_not()
             opname = 'goto_if_not_' + block.exitswitch[0]
             opargs = block.exitswitch[1:]
             if opargs[-1] == '-live-before':
                 livebefore = True
                 opargs = opargs[:-1]
         else:
             assert block.exitswitch.concretetype == lltype.Bool
             opargs = [block.exitswitch]
         #
         lst = self.flatten_list(opargs) + [TLabel(linkfalse)]
         if livebefore:
             self.emitline('-live-')
         self.emitline(opname, *lst)
         if not livebefore:
             self.emitline('-live-', TLabel(linkfalse))
         # true path:
         self.make_link(linktrue)
         # false path:
         self.emitline(Label(linkfalse))
         self.make_link(linkfalse)
     #
     else:
         # A switch.
         #
         switches = [
             link for link in block.exits if link.exitcase != 'default'
         ]
         switches.sort(key=lambda link: link.llexitcase)
         kind = getkind(block.exitswitch.concretetype)
         assert kind == 'int'  # XXX
         #
         # A switch on an integer, implementable efficiently with the
         # help of a SwitchDictDescr.  We use this even if there are
         # very few cases: in pyjitpl.py, opimpl_switch() will promote
         # the int only if it matches one of the cases.
         from rpython.jit.codewriter.jitcode import SwitchDictDescr
         switchdict = SwitchDictDescr()
         switchdict._labels = []
         self.emitline('-live-')  # for 'guard_value'
         self.emitline('switch', self.getcolor(block.exitswitch),
                       switchdict)
         # emit the default path
         if block.exits[-1].exitcase == 'default':
             self.make_link(block.exits[-1])
         else:
             self.emitline("unreachable")
             self.emitline("---")
         #
         for switch in switches:
             key = lltype.cast_primitive(lltype.Signed, switch.llexitcase)
             switchdict._labels.append((key, TLabel(switch)))
             # emit code for that path
             # note: we need a -live- for all the 'guard_false' we produce
             # if the switched value doesn't match any case.
             self.emitline(Label(switch))
             self.emitline('-live-')
             self.make_link(switch)
Exemplo n.º 58
0
    def get_integer_max(self):
        if getkind(self.FIELD) != 'int':
            assert False

        return intbounds.get_integer_max(
            not _is_signed_kind(self.FIELD), rffi.sizeof(self.FIELD))
Exemplo n.º 59
0
    def rewrite_jit_merge_point(self, jd, policy):
        #
        # Mutate the original portal graph from this:
        #
        #       def original_portal(..):
        #           stuff
        #           while 1:
        #               jit_merge_point(*args)
        #               more stuff
        #
        # to that:
        #
        #       def original_portal(..):
        #           stuff
        #           return portal_runner(*args)
        #
        #       def portal_runner(*args):
        #           while 1:
        #               try:
        #                   return portal(*args)
        #               except ContinueRunningNormally, e:
        #                   *args = *e.new_args
        #               except DoneWithThisFrame, e:
        #                   return e.return
        #               except ExitFrameWithException, e:
        #                   raise Exception, e.value
        #
        #       def portal(*args):
        #           while 1:
        #               more stuff
        #
        origportalgraph = jd._jit_merge_point_in
        portalgraph = jd.portal_graph
        PORTALFUNC = jd._PORTAL_FUNCTYPE

        # ____________________________________________________________
        # Prepare the portal_runner() helper
        #
        from rpython.jit.metainterp.warmstate import specialize_value
        from rpython.jit.metainterp.warmstate import unspecialize_value
        portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal',
                                         graph=portalgraph)
        jd._portal_ptr = portal_ptr
        #
        portalfunc_ARGS = []
        nums = {}
        for i, ARG in enumerate(PORTALFUNC.ARGS):
            kind = history.getkind(ARG)
            assert kind != 'void'
            if i < len(jd.jitdriver.greens):
                color = 'green'
            else:
                color = 'red'
            attrname = '%s_%s' % (color, kind)
            count = nums.get(attrname, 0)
            nums[attrname] = count + 1
            portalfunc_ARGS.append((ARG, attrname, count))
        portalfunc_ARGS = unrolling_iterable(portalfunc_ARGS)
        #
        rtyper = self.translator.rtyper
        RESULT = PORTALFUNC.RESULT
        result_kind = history.getkind(RESULT)
        ts = self.cpu.ts
        state = jd.warmstate
        maybe_compile_and_run = jd._maybe_compile_and_run_fn

        def ll_portal_runner(*args):
            start = True
            while 1:
                try:
                    # maybe enter from the function's start.  Note that the
                    # 'start' variable is constant-folded away because it's
                    # the first statement in the loop.
                    if start:
                        maybe_compile_and_run(
                            state.increment_function_threshold, *args)
                    #
                    # then run the normal portal function, i.e. the
                    # interpreter's main loop.  It might enter the jit
                    # via maybe_enter_jit(), which typically ends with
                    # handle_fail() being called, which raises on the
                    # following exceptions --- catched here, because we
                    # want to interrupt the whole interpreter loop.
                    return support.maybe_on_top_of_llinterp(rtyper,
                                                      portal_ptr)(*args)
                except jitexc.ContinueRunningNormally, e:
                    args = ()
                    for ARGTYPE, attrname, count in portalfunc_ARGS:
                        x = getattr(e, attrname)[count]
                        x = specialize_value(ARGTYPE, x)
                        args = args + (x,)
                    start = False
                    continue
                except jitexc.DoneWithThisFrameVoid:
                    assert result_kind == 'void'
                    return
                except jitexc.DoneWithThisFrameInt, e:
                    assert result_kind == 'int'
                    return specialize_value(RESULT, e.result)
Exemplo n.º 60
0
    def get_integer_max(self):
        if getkind(self.FIELD) != 'int':
            assert False

        return intbounds.get_integer_max(not _is_signed_kind(self.FIELD),
                                         rffi.sizeof(self.FIELD))