Example #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) == 2 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[2:], 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 == []
Example #2
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) == 2 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[2:], 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 == []
Example #3
0
 def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
     arg_types = []
     for ARG in ARGS:
         token = history.getkind(ARG)
         if token != "void":
             if token == "float" and longlong.is_longlong(ARG):
                 token = "L"
             arg_types.append(token[0])
     token = history.getkind(RESULT)
     if token == "float" and longlong.is_longlong(RESULT):
         token = "L"
     return self.getdescr(0, token[0], extrainfo=extrainfo, arg_types="".join(arg_types))
Example #4
0
 def make_dependencies(self):
     dg = DependencyGraph()
     for block in self.graph.iterblocks():
         # Compute die_at = {Variable: index_of_operation_with_last_usage}
         die_at = dict.fromkeys(block.inputargs, 0)
         for i, op in enumerate(block.operations):
             for v in op.args:
                 if isinstance(v, Variable):
                     die_at[v] = i
                 elif isinstance(v, ListOfKind):
                     for v1 in v:
                         if isinstance(v1, Variable):
                             die_at[v1] = i
             if op.result is not None:
                 die_at[op.result] = i + 1
         if isinstance(block.exitswitch, tuple):
             for x in block.exitswitch:
                 die_at.pop(x, None)
         else:
             die_at.pop(block.exitswitch, None)
         for link in block.exits:
             for v in link.args:
                 die_at.pop(v, None)
         die_at = [(value, key) for (key, value) in die_at.items()]
         die_at.sort()
         die_at.append((sys.maxint,))
         # Done.  XXX the code above this line runs 3 times
         # (for kind in KINDS) to produce the same result...
         livevars = [v for v in block.inputargs
                       if getkind(v.concretetype) == self.kind]
         # Add the variables of this block to the dependency graph
         for i, v in enumerate(livevars):
             dg.add_node(v)
             for j in range(i):
                 dg.add_edge(livevars[j], v)
         livevars = set(livevars)
         die_index = 0
         for i, op in enumerate(block.operations):
             while die_at[die_index][0] == i:
                 try:
                     livevars.remove(die_at[die_index][1])
                 except KeyError:
                     pass
                 die_index += 1
             if (op.result is not None and
                 getkind(op.result.concretetype) == self.kind):
                 dg.add_node(op.result)
                 for v in livevars:
                     if getkind(v.concretetype) == self.kind:
                         dg.add_edge(v, op.result)
                 livevars.add(op.result)
     self._depgraph = dg
Example #5
0
File: runner.py Project: ieure/pypy
 def calldescrof(self, FUNC, ARGS, RESULT, extrainfo=None):
     arg_types = []
     for ARG in ARGS:
         token = history.getkind(ARG)
         if token != 'void':
             if token == 'float' and longlong.is_longlong(ARG):
                 token = 'L'
             arg_types.append(token[0])
     token = history.getkind(RESULT)
     if token == 'float' and longlong.is_longlong(RESULT):
         token = 'L'
     return self.getdescr(0, token[0], extrainfo=extrainfo,
                          arg_types=''.join(arg_types))
Example #6
0
 def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
     arg_types = []
     for ARG in ARGS:
         token = history.getkind(ARG)
         if token != 'void':
             if token == 'float' and longlong.is_longlong(ARG):
                 token = 'L'
             arg_types.append(token[0])
     token = history.getkind(RESULT)
     if token == 'float' and longlong.is_longlong(RESULT):
         token = 'L'
     return self.getdescr(0,
                          token[0],
                          extrainfo=extrainfo,
                          arg_types=''.join(arg_types))
Example #7
0
def get_call_descr(gccache, ARGS, RESULT, extrainfo=None):
    arg_classes = []
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == "int":
            if ARG is lltype.SingleFloat:
                arg_classes.append("S")
            else:
                arg_classes.append("i")
        elif kind == "ref":
            arg_classes.append("r")
        elif kind == "float":
            if is_longlong(ARG):
                arg_classes.append("L")
            else:
                arg_classes.append("f")
        else:
            raise NotImplementedError("ARG = %r" % (ARG,))
    arg_classes = "".join(arg_classes)
    cls = getCallDescrClass(RESULT)
    key = (cls, arg_classes, extrainfo)
    cache = gccache._cache_call
    try:
        return cache[key]
    except KeyError:
        calldescr = cls(arg_classes, extrainfo)
        calldescr.create_call_stub(gccache.rtyper, RESULT)
        cache[key] = calldescr
        return calldescr
Example #8
0
 def make_args_specification(self, jd):
     graph, op = jd._jit_merge_point_pos
     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(
         [lltype.Signed, llmemory.GCREF], ASMRESTYPE)
Example #9
0
 def split_graph_and_record_jitdriver(self, graph, block, pos):
     op = block.operations[pos]
     jd = JitDriverStaticData()
     jd._jit_merge_point_pos = (graph, op)
     args = op.args[2:]
     s_binding = self.translator.annotator.binding
     jd._portal_args_s = [s_binding(v) for v in args]
     graph = copygraph(graph)
     graph.startblock.isstartblock = False
     [jmpp] = find_jit_merge_points([graph])
     graph.startblock = support.split_before_jit_merge_point(*jmpp)
     graph.startblock.isstartblock = True
     # a crash in the following checkgraph() means that you forgot
     # to list some variable in greens=[] or reds=[] in JitDriver.
     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)
Example #10
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(
         [lltype.Signed, llmemory.GCREF], ASMRESTYPE)
Example #11
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)
     # 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)
Example #12
0
 def decode_box_of_type(self, TYPE, tagged):
     kind = getkind(TYPE)
     if kind == 'int':     kind = INT
     elif kind == 'ref':   kind = REF
     elif kind == 'float': kind = FLOAT
     else: raise AssertionError(kind)
     return self.decode_box(tagged, kind)
Example #13
0
def get_call_descr(gccache, ARGS, RESULT, extrainfo=None):
    arg_classes = []
    for ARG in ARGS:
        kind = getkind(ARG)
        if   kind == 'int':
            if ARG is lltype.SingleFloat:
                arg_classes.append('S')
            else:
                arg_classes.append('i')
        elif kind == 'ref': arg_classes.append('r')
        elif kind == 'float':
            if is_longlong(ARG):
                arg_classes.append('L')
            else:
                arg_classes.append('f')
        else:
            raise NotImplementedError('ARG = %r' % (ARG,))
    arg_classes = ''.join(arg_classes)
    cls = getCallDescrClass(RESULT)
    key = (cls, arg_classes, extrainfo)
    cache = gccache._cache_call
    try:
        return cache[key]
    except KeyError:
        calldescr = cls(arg_classes, extrainfo)
        calldescr.create_call_stub(gccache.rtyper, RESULT)
        cache[key] = calldescr
        return calldescr
Example #14
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)
Example #15
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)
Example #16
0
    def __init__(self, TYPE, fieldname):
        self.TYPE = TYPE
        self.fieldname = fieldname

        _, 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._is_pointer_field = (history.getkind(T) == 'ref')
        self._is_float_field = (history.getkind(T) == 'float')
Example #17
0
File: runner.py Project: ieure/pypy
    def __init__(self, TYPE, fieldname):
        self.TYPE = TYPE
        self.fieldname = fieldname

        _, 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._is_pointer_field = (history.getkind(T) == 'ref')
        self._is_float_field = (history.getkind(T) == 'float')
Example #18
0
 def arraydescrof(self, A):
     assert A.OF != lltype.Void
     size = symbolic.get_size(A)
     if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive):
         token = history.getkind(A.OF)[0]
     elif isinstance(A.OF, lltype.Struct):
         token = 's'
     else:
         token = '?'
     return self.getdescr(size, token)
Example #19
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
Example #20
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) == 2 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[2:], 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 == []
Example #21
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
Example #22
0
 def _sort(args_v):
     from pypy.jit.metainterp.history import getkind
     lst = [v for v in args_v if v.concretetype is not lltype.Void]
     _kind2count = {'int': 1, 'ref': 2, 'float': 3}
     lst2 = sorted(lst, key=lambda v: _kind2count[getkind(v.concretetype)])
     # a crash here means that you have to reorder the variable named in
     # the JitDriver.  Indeed, greens and reds must both be sorted: first
     # all INTs, followed by all REFs, followed by all FLOATs.
     assert lst == lst2
     return lst
Example #23
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 == []
Example #24
0
 def arraydescrof(self, A):
     assert A.OF != lltype.Void
     assert isinstance(A, lltype.GcArray) or A._hints.get('nolength', False)
     size = symbolic.get_size(A)
     if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive):
         token = history.getkind(A.OF)[0]
     elif isinstance(A.OF, lltype.Struct):
         token = 's'
     else:
         token = '?'
     return self.getdescr(size, token)
Example #25
0
 def arraydescrof(self, A):
     assert A.OF != lltype.Void
     assert isinstance(A, lltype.GcArray) or A._hints.get('nolength', False)
     size = symbolic.get_size(A)
     if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive):
         token = history.getkind(A.OF)[0]
     elif isinstance(A.OF, lltype.Struct):
         token = 's'
     else:
         token = '?'
     return self.getdescr(size, token)
Example #26
0
 def load_value_of_type(self, TYPE, tagged):
     from pypy.jit.metainterp.warmstate import specialize_value
     kind = getkind(TYPE)
     if kind == 'int':
         x = self.decode_int(tagged)
     elif kind == 'ref':
         x = self.decode_ref(tagged)
     elif kind == 'float':
         x = self.decode_float(tagged)
     else:
         raise AssertionError(kind)
     return specialize_value(TYPE, x)
Example #27
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, ))
Example #28
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) == 2 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[2:], 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 == []
Example #29
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 == []
Example #30
0
 def __init__(self, TYPE, fieldname):
     DescrWithKey.__init__(self, (TYPE, fieldname))
     from pypy.jit.backend.llgraph.runner import boxresult
     from pypy.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')
Example #31
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,))
Example #32
0
 def __init__(self, TYPE):
     DescrWithKey.__init__(self, TYPE)
     from pypy.jit.backend.llgraph.runner import boxresult
     from pypy.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')
Example #33
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 pypy.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 op0.args[1] == 'calldescr'
    assert isinstance(op0.args[2], IndirectCallTargets)
    assert op0.args[2].lst == ['somejitcode1', 'somejitcode2']
    assert len(op0.args) == 3 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[3:], 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 == []
Example #34
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)
Example #35
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)
Example #36
0
 def _sort(args_v, is_green):
     from pypy.jit.metainterp.history import getkind
     lst = [v for v in args_v if v.concretetype is not lltype.Void]
     if is_green:
         assert len(lst) == len(args_v), (
             "not supported so far: 'greens' variables contain Void")
     _kind2count = {'int': 1, 'ref': 2, 'float': 3}
     lst2 = sorted(lst, key=lambda v: _kind2count[getkind(v.concretetype)])
     # a crash here means that you have to reorder the variable named in
     # the JitDriver.  Indeed, greens and reds must both be sorted: first
     # all INTs, followed by all REFs, followed by all FLOATs.
     assert lst == lst2
     return lst
Example #37
0
    def __init__(self, TYPE):
        self.TYPE = TYPE
        self.ARRAY = ARRAY = ootype.Array(TYPE)

        def create():
            return boxresult(TYPE, ootype.new(TYPE))

        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()
            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):
            obj = box.getref(ootype.ROOT)
            return history.BoxInt(ootype.instanceof(obj, TYPE))

        self.create = create
        self.create_array = create_array
        self.getarrayitem = getarrayitem
        self.setarrayitem = setarrayitem
        self.getarraylength = getarraylength
        self.instanceof = instanceof
        self._is_array_of_pointers = history.getkind(TYPE) == "ref"
        self._is_array_of_floats = history.getkind(TYPE) == "float"
Example #38
0
    def __init__(self, TYPE):
        self.TYPE = TYPE
        self.ARRAY = ARRAY = ootype.Array(TYPE)

        def create():
            return boxresult(TYPE, ootype.new(TYPE))

        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()
            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):
            obj = box.getref(ootype.ROOT)
            return history.BoxInt(ootype.instanceof(obj, TYPE))

        self.create = create
        self.create_array = create_array
        self.getarrayitem = getarrayitem
        self.setarrayitem = setarrayitem
        self.getarraylength = getarraylength
        self.instanceof = instanceof
        self._is_array_of_pointers = (history.getkind(TYPE) == 'ref')
        self._is_array_of_floats = (history.getkind(TYPE) == 'float')
Example #39
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 pypy.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 op0.args[1] == 'calldescr'
    assert isinstance(op0.args[2], IndirectCallTargets)
    assert op0.args[2].lst == ['somejitcode1', 'somejitcode2']
    assert len(op0.args) == 3 + len(expectedkind)
    for sublist, kind1 in zip(op0.args[3:], 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 == []
Example #40
0
 def _try_coalesce(self, v, w):
     if isinstance(v, Variable) and getkind(v.concretetype) == self.kind:
         dg = self._depgraph
         uf = self._unionfind
         v0 = uf.find_rep(v)
         w0 = uf.find_rep(w)
         if v0 is not w0 and v0 not in dg.neighbours[w0]:
             _, rep, _ = uf.union(v0, w0)
             assert uf.find_rep(v0) is uf.find_rep(w0) is rep
             if rep is v0:
                 dg.coalesce(w0, v0)
             else:
                 assert rep is w0
                 dg.coalesce(v0, w0)
Example #41
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("---")
Example #42
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("---")
Example #43
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,))
Example #44
0
def get_call_descr(gccache, ARGS, RESULT, extrainfo=None):
    arg_classes = []
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == 'int': arg_classes.append('i')
        elif kind == 'ref': arg_classes.append('r')
        elif kind == 'float': arg_classes.append('f')
        else:
            raise NotImplementedError('ARG = %r' % (ARG, ))
    arg_classes = ''.join(arg_classes)
    cls = getCallDescrClass(RESULT)
    key = (cls, arg_classes, extrainfo)
    cache = gccache._cache_call
    try:
        return cache[key]
    except KeyError:
        calldescr = cls(arg_classes, extrainfo)
        cache[key] = calldescr
        return calldescr
Example #45
0
 def make_args_specification(self):
     graph, block, index = self.jit_merge_point_pos
     op = block.operations[index]
     args = op.args[2:]
     ALLARGS = []
     self.green_args_spec = []
     self.red_args_types = []
     for i, v in enumerate(args):
         TYPE = v.concretetype
         ALLARGS.append(TYPE)
         if i < len(self.jitdriver.greens):
             self.green_args_spec.append(TYPE)
         else:
             self.red_args_types.append(history.getkind(TYPE))
     self.num_green_args = len(self.green_args_spec)
     RESTYPE = graph.getreturnvar().concretetype
     (self.JIT_ENTER_FUNCTYPE,
      self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
     (self.PORTAL_FUNCTYPE,
      self.PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE)
Example #46
0
def get_call_descr(gccache, ARGS, RESULT):
    arg_classes = []
    for ARG in ARGS:
        kind = getkind(ARG)
        if kind == "int":
            arg_classes.append("i")
        elif kind == "ref":
            arg_classes.append("r")
        elif kind == "float":
            arg_classes.append("f")
        else:
            raise NotImplementedError("ARG = %r" % (ARG,))
    arg_classes = "".join(arg_classes)
    cls = getCallDescrClass(RESULT)
    key = (cls, arg_classes)
    cache = gccache._cache_call
    try:
        return cache[key]
    except KeyError:
        calldescr = cls(arg_classes)
        cache[key] = calldescr
        return calldescr
Example #47
0
 def make_args_specification(self):
     graph, block, index = self.jit_merge_point_pos
     op = block.operations[index]
     args = op.args[2:]
     ALLARGS = []
     self.green_args_spec = []
     self.red_args_types = []
     for i, v in enumerate(args):
         TYPE = v.concretetype
         ALLARGS.append(TYPE)
         if i < len(self.jitdriver.greens):
             self.green_args_spec.append(TYPE)
         else:
             self.red_args_types.append(history.getkind(TYPE))
     self.num_green_args = len(self.green_args_spec)
     RESTYPE = graph.getreturnvar().concretetype
     (self.JIT_ENTER_FUNCTYPE,
      self.PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
     (self.PORTAL_FUNCTYPE,
      self.PTR_PORTAL_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, RESTYPE)
     (_, self.PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType(
         [lltype.Signed, llmemory.GCREF], RESTYPE)
Example #48
0
def _run_with_machine_code(testself, args):
    metainterp = testself.metainterp
    num_green_args = metainterp.jitdriver_sd.num_green_args
    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
    if len(loop_tokens) != 1:
        return NotImplemented
    # a loop was successfully created by _run_with_pyjitpl(); call it
    cpu = metainterp.cpu
    for i in range(len(args) - num_green_args):
        x = args[num_green_args + i]
        typecode = history.getkind(lltype.typeOf(x))
        set_future_value(cpu, i, x, typecode)
    faildescr = cpu.execute_token(loop_tokens[0])
    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
    if metainterp.jitdriver_sd.result_type == history.INT:
        return cpu.get_latest_value_int(0)
    elif metainterp.jitdriver_sd.result_type == history.REF:
        return cpu.get_latest_value_ref(0)
    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
        return cpu.get_latest_value_float(0)
    else:
        return None
Example #49
0
 def arraydescrof(A):
     assert isinstance(A, lltype.GcArray)
     assert A.OF != lltype.Void
     size = symbolic.get_size(A)
     token = history.getkind(A.OF)
     return Descr(size, token[0])
Example #50
0
    def rewrite_jit_merge_point(self, 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 = self.jit_merge_point_pos[0]
        portalgraph = self.portal_graph
        PORTALFUNC = self.PORTAL_FUNCTYPE

        # ____________________________________________________________
        # Prepare the portal_runner() helper
        #
        portal_ptr = self.cpu.ts.functionptr(PORTALFUNC,
                                             'portal',
                                             graph=portalgraph)
        self.portal_ptr = portal_ptr
        portalfunc_ARGS = unrolling_iterable([
            (i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)
        ])

        class DoneWithThisFrameVoid(JitException):
            def __str__(self):
                return 'DoneWithThisFrameVoid()'

        class DoneWithThisFrameInt(JitException):
            def __init__(self, result):
                assert lltype.typeOf(result) is lltype.Signed
                self.result = result

            def __str__(self):
                return 'DoneWithThisFrameInt(%s)' % (self.result, )

        class DoneWithThisFrameRef(JitException):
            def __init__(self, cpu, result):
                assert lltype.typeOf(result) == cpu.ts.BASETYPE
                self.result = result

            def __str__(self):
                return 'DoneWithThisFrameRef(%s)' % (self.result, )

        class DoneWithThisFrameFloat(JitException):
            def __init__(self, result):
                assert lltype.typeOf(result) is lltype.Float
                self.result = result

            def __str__(self):
                return 'DoneWithThisFrameFloat(%s)' % (self.result, )

        class ExitFrameWithExceptionRef(JitException):
            def __init__(self, cpu, value):
                assert lltype.typeOf(value) == cpu.ts.BASETYPE
                self.value = value

            def __str__(self):
                return 'ExitFrameWithExceptionRef(%s)' % (self.value, )

        class ContinueRunningNormally(ContinueRunningNormallyBase):
            def __init__(self, argboxes):
                # accepts boxes as argument, but unpacks them immediately
                # before we raise the exception -- the boxes' values will
                # be modified in a 'finally' by restore_patched_boxes().
                from pypy.jit.metainterp.warmstate import unwrap
                for i, name, ARG in portalfunc_ARGS:
                    v = unwrap(ARG, argboxes[i])
                    setattr(self, name, v)

            def __str__(self):
                return 'ContinueRunningNormally(%s)' % (', '.join(
                    map(str, self.args)), )

        self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
        self.DoneWithThisFrameInt = DoneWithThisFrameInt
        self.DoneWithThisFrameRef = DoneWithThisFrameRef
        self.DoneWithThisFrameFloat = DoneWithThisFrameFloat
        self.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
        self.ContinueRunningNormally = ContinueRunningNormally
        self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
        self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
        self.metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
        self.metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrameFloat
        self.metainterp_sd.ExitFrameWithExceptionRef = ExitFrameWithExceptionRef
        self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
        rtyper = self.translator.rtyper
        RESULT = PORTALFUNC.RESULT
        result_kind = history.getkind(RESULT)
        ts = self.cpu.ts

        def ll_portal_runner(*args):
            while 1:
                try:
                    return support.maybe_on_top_of_llinterp(
                        rtyper, portal_ptr)(*args)
                except ContinueRunningNormally, e:
                    args = ()
                    for _, name, _ in portalfunc_ARGS:
                        v = getattr(e, name)
                        args = args + (v, )
                except DoneWithThisFrameVoid:
                    assert result_kind == 'void'
                    return
                except DoneWithThisFrameInt, e:
                    assert result_kind == 'int'
                    return lltype.cast_primitive(RESULT, e.result)
Example #51
0
 def fielddescrof(self, S, fieldname):
     ofs, size = symbolic.get_field_token(S, fieldname)
     token = history.getkind(getattr(S, fieldname))
     return self.getdescr(ofs, token[0], name=fieldname)
Example #52
0
 def interiorfielddescrof(self, A, fieldname):
     S = A.OF
     width = symbolic.get_size(A)
     ofs, size = symbolic.get_field_token(S, fieldname)
     token = history.getkind(getattr(S, fieldname))
     return self.getdescr(ofs, token[0], name=fieldname, width=width)
Example #53
0
def _get_jitcodes(testself,
                  CPUClass,
                  func,
                  values,
                  type_system,
                  supports_longlong=False,
                  translationoptions={},
                  **kwds):
    from pypy.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):
            cell = self.jit_cell_at_key(greenkey)
            cell.set_procedure_token(procedure_token)

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

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

        def jit_cell_at_key(self, greenkey):
            assert greenkey == []
            return self._cell

        _cell = FakeJitCell()

        trace_limit = sys.maxint
        enable_opts = ALL_OPTS_DICT

    func._jit_unroll_safe_ = True
    rtyper = support.annotate(func,
                              values,
                              type_system=type_system,
                              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 = "???"

    stats = history.Stats()
    cpu = CPUClass(rtyper, stats, None, False)
    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
    cw.debug = True
    testself.cw = cw
    policy = JitPolicy()
    policy.set_supports_floats(True)
    policy.set_supports_longlong(supports_longlong)
    cw.find_all_graphs(policy)
    #
    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)
Example #54
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.
            #
            def emitdefaultpath():
                if block.exits[-1].exitcase == 'default':
                    self.make_link(block.exits[-1])
                else:
                    self.emitline("unreachable")
                    self.emitline("---")

            #
            self.emitline('-live-')
            switches = [
                link for link in block.exits if link.exitcase != 'default'
            ]
            switches.sort(key=lambda link: link.llexitcase)
            kind = getkind(block.exitswitch.concretetype)
            if len(switches) >= 5 and kind == 'int':
                # A large switch on an integer, implementable efficiently
                # with the help of a SwitchDictDescr
                from pypy.jit.codewriter.jitcode import SwitchDictDescr
                switchdict = SwitchDictDescr()
                switchdict._labels = []
                self.emitline('switch', self.getcolor(block.exitswitch),
                              switchdict)
                emitdefaultpath()
                #
                for switch in switches:
                    key = lltype.cast_primitive(lltype.Signed,
                                                switch.llexitcase)
                    switchdict._labels.append((key, TLabel(switch)))
                    # emit code for that path
                    self.emitline(Label(switch))
                    self.make_link(switch)
            #
            else:
                # A switch with several possible answers, though not too
                # many of them -- a chain of int_eq comparisons is fine
                assert kind == 'int'  # XXX
                color = self.getcolor(block.exitswitch)
                self.emitline('int_guard_value', color)
                for switch in switches:
                    # make the case described by 'switch'
                    self.emitline(
                        'goto_if_not_int_eq', color,
                        Constant(switch.llexitcase,
                                 block.exitswitch.concretetype),
                        TLabel(switch))
                    # emit code for the "taken" path
                    self.make_link(switch)
                    # finally, emit the label for the "non-taken" path
                    self.emitline(Label(switch))
                #
                emitdefaultpath()
Example #55
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)
Example #56
0
    def rewrite_jit_merge_point(self, 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 = self.jit_merge_point_pos[0]
        portalgraph = self.portal_graph
        PORTALFUNC = self.PORTAL_FUNCTYPE

        # ____________________________________________________________
        # Prepare the portal_runner() helper
        #
        portal_ptr = self.cpu.ts.functionptr(PORTALFUNC, 'portal',
                                         graph = portalgraph)
        self.portal_ptr = portal_ptr
        portalfunc_ARGS = unrolling_iterable(
            [(i, 'arg%d' % i, ARG) for i, ARG in enumerate(PORTALFUNC.ARGS)])


        rtyper = self.translator.rtyper
        RESULT = PORTALFUNC.RESULT
        result_kind = history.getkind(RESULT)
        ts = self.cpu.ts

        def ll_portal_runner(*args):
            while 1:
                try:
                    self.maybe_enter_from_start_fn(*args)
                    return support.maybe_on_top_of_llinterp(rtyper,
                                                      portal_ptr)(*args)
                except self.ContinueRunningNormally, e:
                    args = ()
                    for _, name, _ in portalfunc_ARGS:
                        v = getattr(e, name)
                        args = args + (v,)
                except self.DoneWithThisFrameVoid:
                    assert result_kind == 'void'
                    return
                except self.DoneWithThisFrameInt, e:
                    assert result_kind == 'int'
                    return lltype.cast_primitive(RESULT, e.result)
Example #57
0
def perform_register_allocation(graph, kind):
    checkkind = lambda v: getkind(v.concretetype) == kind
    return regalloc.perform_register_allocation(graph, checkkind, ListOfKind)
Example #58
0
    def __init__(self, warmrunnerdesc):
        self.warmrunnerdesc = warmrunnerdesc
        jitdriver = warmrunnerdesc.jitdriver
        cpu = warmrunnerdesc.cpu
        self.cpu = cpu
        self.VABLERTI = cpu.ts.get_VABLERTI()
        self.null_vable_rti = cpu.ts.nullptr(deref(self.VABLERTI))
        self.BoxArray = cpu.ts.BoxRef
        #
        assert len(jitdriver.virtualizables) == 1  # for now
        [vname] = jitdriver.virtualizables
        index = len(jitdriver.greens) + jitdriver.reds.index(vname)
        self.index_of_virtualizable = index
        VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index]
        while 'virtualizable2_accessor' not in deref(VTYPEPTR)._hints:
            VTYPEPTR = cpu.ts.get_superclass(VTYPEPTR)
        self.VTYPEPTR = VTYPEPTR
        self.VTYPE = VTYPE = deref(VTYPEPTR)
        self.null_vable = cpu.ts.nullptr(VTYPE)
        #
        accessor = VTYPE._hints['virtualizable2_accessor']
        all_fields = accessor.fields
        static_fields = []
        array_fields = []
        for name, suffix in all_fields.iteritems():
            if suffix == '[*]':
                array_fields.append(name)
            else:
                static_fields.append(name)
        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, ootype.Array))
            assert isinstance(ARRAY, (lltype.GcArray, ootype.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
        ]
        #
        getlength = cpu.ts.getlength
        getarrayitem = cpu.ts.getarrayitem
        setarrayitem = cpu.ts.setarrayitem

        #
        def read_boxes(cpu, 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):
            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 check_boxes(virtualizable, boxes):
            # 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):
            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):
            j = 0
            for _, fieldname in unroll_array_fields:
                if arrayindex == j:
                    lst = getattr(virtualizable, fieldname)
                    return getlength(lst)
                j = j + 1
            assert False, "invalid arrayindex"

        #
        unroll_static_fields = unrolling_iterable(
            zip(FIELDTYPES, static_fields))
        unroll_array_fields = unrolling_iterable(
            zip(ARRAYITEMTYPES, array_fields))
        self.read_boxes = read_boxes
        self.write_boxes = write_boxes
        self.check_boxes = check_boxes
        self.get_index_in_array = get_index_in_array
        self.get_array_length = get_array_length