Beispiel #1
0
    def do_inline(self, block, index_operation):
        splitlink = split_block(None, block, index_operation)
        afterblock = splitlink.target
        # these variables have to be passed along all the links in the inlined
        # graph because the original function needs them in the blocks after
        # the inlined function
        # for every inserted block we need a new copy of these variables,
        # this copy is created with the method passon_vars
        self.original_passon_vars = [arg for arg in block.exits[0].args
                                         if isinstance(arg, Variable)]
        assert afterblock.operations[0].opname == self.op.opname
        self.op = afterblock.operations.pop(0)
        #vars that need to be passed through the blocks of the inlined function
        linktoinlined = splitlink
        copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
        copiedstartblock.isstartblock = False
        #find args passed to startblock of inlined function
        passon_args = []
        for arg in self.op.args[1:]:
            if isinstance(arg, Constant):
                passon_args.append(arg)
            else:
                index = afterblock.inputargs.index(arg)
                passon_args.append(linktoinlined.args[index])
        passon_args += self.original_passon_vars

        if self.op.opname == 'oosend' and not isinstance(self.op.args[1], Constant):
            # if we try to inline a graph defined in a superclass, the
            # type of 'self' on the graph differs from the current
            linkv = passon_args[0]
            inputv = copiedstartblock.inputargs[0]
            LINK_SELF = linkv.concretetype
            INPUT_SELF = inputv.concretetype
            if LINK_SELF != INPUT_SELF:
                # need to insert an upcast
                if ootype.isSubclass(LINK_SELF, INPUT_SELF):
                    opname = 'ooupcast'
                else:
                    assert ootype.isSubclass(INPUT_SELF, LINK_SELF)
                    opname = 'oodowncast'
                v = Variable()
                v.concretetype = INPUT_SELF
                upcast = SpaceOperation(opname, [linkv], v)
                block.operations.append(upcast)
                passon_args[0] = v

        #rewire blocks
        linktoinlined.target = copiedstartblock
        linktoinlined.args = passon_args
        afterblock.inputargs = [self.op.result] + afterblock.inputargs
        if self.graph_to_inline.returnblock in self.entrymap:
            self.rewire_returnblock(afterblock) 
        if self.graph_to_inline.exceptblock in self.entrymap:
            self.rewire_exceptblock(afterblock)
        if self.exception_guarded:
            assert afterblock.exits[0].exitcase is None
            afterblock.recloseblock(afterblock.exits[0])
            afterblock.exitswitch = None
        self.search_for_calls(afterblock)
        self.search_for_calls(block)
Beispiel #2
0
 def fromclasstype(self, vclass, llops):
     assert ootype.isSubclass(vclass.concretetype, META)
     if self.lowleveltype == ootype.Class:
         c_class_ = inputconst(ootype.Void, 'class_')
         return llops.genop('oogetfield', [vclass, c_class_],
                            resulttype=ootype.Class)
     else:
         assert ootype.isSubclass(self.lowleveltype, vclass.concretetype)
         return llops.genop('oodowncast', [vclass],
                            resulttype=self.lowleveltype)
Beispiel #3
0
 def fromclasstype(self, vclass, llops):
     assert ootype.isSubclass(vclass.concretetype, META)
     if self.lowleveltype == ootype.Class:
         c_class_ = inputconst(ootype.Void, 'class_')
         return llops.genop('oogetfield', [vclass, c_class_],
                 resulttype=ootype.Class)
     else:
         assert ootype.isSubclass(self.lowleveltype, vclass.concretetype)
         return llops.genop('oodowncast', [vclass],
                 resulttype=self.lowleveltype)
Beispiel #4
0
    def attach_methods_to_subclasses(self):
        # in ootype, it might happen that a method is defined in the
        # superclass but the annotator discovers that it's always called
        # through instances of a subclass (e.g. because of specialization, see
        # test_rclass.test_method_specialized_with_subclass).  In that cases,
        # we copy the method also in the ootype.Instance of the subclass, so
        # that the type of v_self coincides with the type returned by
        # _lookup().
        assert self.type_system.name == 'ootypesystem'

        def allclasses(TYPE, seen):
            '''Yield TYPE and all its subclasses'''
            if TYPE in seen:
                return
            seen.add(TYPE)
            yield TYPE
            for SUB in TYPE._subclasses:
                for T in allclasses(SUB, seen):
                    yield T

        for TYPE in allclasses(ootype.ROOT, set()):
            for methname, meth in TYPE._methods.iteritems():
                try:
                    graph = meth.graph
                except AttributeError:
                    continue
                SELF = graph.getargs()[0].concretetype
                if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
                    # the annotator found that this method has a more precise
                    # type. Attach it to the proper subclass, so that the type
                    # of 'self' coincides with the type returned by _lookup(),
                    # else we might have type errors
                    if methname not in SELF._methods:
                        ootype.addMethods(SELF, {methname: meth})
Beispiel #5
0
def match_virtualizable_type(TYPE, VTYPEPTR):
    if isinstance(TYPE, ootype.Instance):
        # ootype only: any subtype may be used
        return ootype.isSubclass(TYPE, VTYPEPTR)
    else:
        # lltype, or ootype with a TYPE that is e.g. an ootype.Record
        return TYPE == VTYPEPTR
Beispiel #6
0
    def attach_methods_to_subclasses(self):
        # in ootype, it might happen that a method is defined in the
        # superclass but the annotator discovers that it's always called
        # through instances of a subclass (e.g. because of specialization, see
        # test_rclass.test_method_specialized_with_subclass).  In that cases,
        # we copy the method also in the ootype.Instance of the subclass, so
        # that the type of v_self coincides with the type returned by
        # _lookup().
        assert self.type_system.name == 'ootypesystem'
        def allclasses(TYPE, seen):
            '''Yield TYPE and all its subclasses'''
            if TYPE in seen:
                return
            seen.add(TYPE)
            yield TYPE
            for SUB in TYPE._subclasses:
                for T in allclasses(SUB, seen):
                    yield T

        for TYPE in allclasses(ootype.ROOT, set()):
            for methname, meth in TYPE._methods.iteritems():
                try:
                    graph = meth.graph
                except AttributeError:
                    continue
                SELF = graph.getargs()[0].concretetype
                if TYPE != SELF and ootype.isSubclass(SELF, TYPE):
                    # the annotator found that this method has a more precise
                    # type. Attach it to the proper subclass, so that the type
                    # of 'self' coincides with the type returned by _lookup(),
                    # else we might have type errors
                    if methname not in SELF._methods:
                        ootype.addMethods(SELF, {methname: meth})
Beispiel #7
0
def match_virtualizable_type(TYPE, VTYPEPTR):
    if isinstance(TYPE, ootype.Instance):
        # ootype only: any subtype may be used
        return ootype.isSubclass(TYPE, VTYPEPTR)
    else:
        # lltype, or ootype with a TYPE that is e.g. an ootype.Record
        return TYPE == VTYPEPTR
Beispiel #8
0
    def do_inline(self, block, index_operation):
        splitlink = split_block(None, block, index_operation)
        afterblock = splitlink.target
        # these variables have to be passed along all the links in the inlined
        # graph because the original function needs them in the blocks after
        # the inlined function
        # for every inserted block we need a new copy of these variables,
        # this copy is created with the method passon_vars
        self.original_passon_vars = [arg for arg in block.exits[0].args
                                         if isinstance(arg, Variable)]
        n = 0
        while afterblock.operations[n].opname == 'keepalive':
            n += 1
        assert afterblock.operations[n].opname == self.op.opname
        self.op = afterblock.operations.pop(n)
        #vars that need to be passed through the blocks of the inlined function
        linktoinlined = splitlink
        copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
        copiedstartblock.isstartblock = False
        #find args passed to startblock of inlined function
        passon_args = []
        for arg in self.op.args[1:]:
            if isinstance(arg, Constant):
                passon_args.append(arg)
            else:
                index = afterblock.inputargs.index(arg)
                passon_args.append(linktoinlined.args[index])
        passon_args += self.original_passon_vars

        if self.op.opname == 'oosend' and not isinstance(self.op.args[1], Constant):
            # if we try to inline a graph defined in a superclass, the
            # type of 'self' on the graph differs from the current
            linkv = passon_args[0]
            inputv = copiedstartblock.inputargs[0]
            LINK_SELF = linkv.concretetype
            INPUT_SELF = inputv.concretetype
            if LINK_SELF != INPUT_SELF:
                # need to insert an upcast
                assert ootype.isSubclass(LINK_SELF, INPUT_SELF)
                v = Variable()
                v.concretetype = INPUT_SELF
                upcast = SpaceOperation('ooupcast', [linkv], v)
                block.operations.append(upcast)
                passon_args[0] = v

        #rewire blocks
        linktoinlined.target = copiedstartblock
        linktoinlined.args = passon_args
        afterblock.inputargs = [self.op.result] + afterblock.inputargs
        if self.graph_to_inline.returnblock in self.entrymap:
            self.rewire_returnblock(afterblock) 
        if self.graph_to_inline.exceptblock in self.entrymap:
            self.rewire_exceptblock(afterblock)
        if self.exception_guarded:
            assert afterblock.exits[0].exitcase is None
            afterblock.recloseblock(afterblock.exits[0])
            afterblock.exitswitch = None
        self.search_for_calls(afterblock)
        self.search_for_calls(block)
Beispiel #9
0
    def _translate_instance(self, OOTYPE):
        assert isinstance(OOTYPE, ootype.Instance)
        assert OOTYPE is not ootype.ROOT

        # Create class object if it does not already exist:
        if OOTYPE in self._classes:
            return self._classes[OOTYPE]

        # Create the class object first
        clsnm = self._pkg(self._uniq(OOTYPE._name))
        clsobj = node.Class(clsnm)
        self._classes[OOTYPE] = clsobj

        # Resolve super class
        assert OOTYPE._superclass
        supercls = self._translate_superclass_of(OOTYPE)
        clsobj.set_super_class(supercls)

        # TODO --- mangle field and method names?  Must be
        # deterministic, or use hashtable to avoid conflicts between
        # classes?

        # Add fields:
        self._translate_class_fields(clsobj, OOTYPE)

        # Add methods:
        for mname, mimpl in OOTYPE._methods.iteritems():
            if not hasattr(mimpl, 'graph'):
                # Abstract method
                METH = mimpl._TYPE
                arglist = [
                    self.lltype_to_cts(ARG) for ARG in METH.ARGS
                    if ARG is not ootype.Void
                ]
                returntype = self.lltype_to_cts(METH.RESULT)
                clsobj.add_abstract_method(
                    jvm.Method.v(clsobj, mname, arglist, returntype))
            else:
                # if the first argument's type is not a supertype of
                # this class it means that this method this method is
                # not really used by the class: don't render it, else
                # there would be a type mismatch.
                args = mimpl.graph.getargs()
                SELF = args[0].concretetype
                if not ootype.isSubclass(OOTYPE, SELF): continue
                mobj = self._function_for_graph(clsobj, mname, False,
                                                mimpl.graph)
                graphs = OOTYPE._lookup_graphs(mname)
                if len(graphs) == 1:
                    mobj.is_final = True
                clsobj.add_method(mobj)

        # currently, we always include a special "dump" method for debugging
        # purposes
        dump_method = node.InstanceDumpMethod(self, OOTYPE, clsobj)
        clsobj.add_method(dump_method)

        self.pending_node(clsobj)
        return clsobj
Beispiel #10
0
 def compute_result_annotation(self, s_value, s_type):
     if isinstance(s_type.const, ootype.OOType):
         TYPE = s_type.const
     else:
         cliClass = s_type.const
         TYPE = cliClass._INSTANCE
     assert ootype.isSubclass(s_value.ootype, TYPE)
     return SomeOOInstance(TYPE)
Beispiel #11
0
 def compute_result_annotation(self, s_value, s_type):
     if isinstance(s_type.const, ootype.OOType):
         TYPE = s_type.const
     else:
         cliClass = s_type.const
         TYPE = cliClass._INSTANCE
     assert ootype.isSubclass(TYPE, s_value.ootype)
     return SomeOOInstance(TYPE)
Beispiel #12
0
 def getruntime(self, expected_type):
     if expected_type == ootype.Class:
         rinstance = getinstancerepr(self.rtyper, self.classdef)
         return ootype.runtimeClass(rinstance.lowleveltype)
     else:
         assert ootype.isSubclass(expected_type, META)
         meta = self.get_meta_instance(cast_to_root_meta=False)
         return ootype.ooupcast(expected_type, meta)
Beispiel #13
0
 def getruntime(self, expected_type):
     if expected_type == ootype.Class:
         rinstance = getinstancerepr(self.rtyper, self.classdef)
         return ootype.runtimeClass(rinstance.lowleveltype)
     else:
         assert ootype.isSubclass(expected_type, META)
         meta = self.get_meta_instance(cast_to_root_meta=False)
         return ootype.ooupcast(expected_type, meta)
Beispiel #14
0
 def _toString(self):
     if ootype.isSubclass(self.INSTANCE, self.db.genoo.EXCEPTION):
         return # don't override the default ToString, which prints a traceback
     self.ilasm.begin_function('ToString', [], 'string', False, 'virtual', 'instance', 'default')
     self.ilasm.opcode('ldarg.0')
     self.ilasm.call('string class [pypylib]pypy.test.Result::InstanceToPython(object)')
     self.ilasm.ret()
     self.ilasm.end_function()
Beispiel #15
0
    def render(self, ilasm):
        if self.is_root(self.INSTANCE):
            return

        self.ilasm = ilasm
        self.gen = CLIBaseGenerator(self.db, ilasm)

        if self.namespace:
            ilasm.begin_namespace(self.namespace)

        ilasm.begin_class(self.name,
                          self.get_base_class(),
                          abstract=self.is_abstract())
        for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems():
            cts_type = self.cts.lltype_to_cts(f_type)
            f_name = self.cts.escape_name(f_name)
            if cts_type != CTS.types.void:
                ilasm.field(f_name, cts_type)

        self._ctor()
        self._toString()

        for m_name, m_meth in self.INSTANCE._methods.iteritems():
            if hasattr(m_meth, 'graph'):
                # if the first argument's type is not a supertype of
                # this class it means that this method this method is
                # not really used by the class: don't render it, else
                # there would be a type mismatch.
                args = m_meth.graph.getargs()
                SELF = args[0].concretetype
                if not ootype.isSubclass(self.INSTANCE, SELF):
                    continue
                f = self.db.genoo.Function(self.db,
                                           m_meth.graph,
                                           m_name,
                                           is_method=True)
                f.render(ilasm)
            else:
                # abstract method
                METH = m_meth._TYPE
                arglist = [(self.cts.lltype_to_cts(ARG), 'v%d' % i)
                           for i, ARG in enumerate(METH.ARGS)
                           if ARG is not ootype.Void]
                returntype = self.cts.lltype_to_cts(METH.RESULT)
                ilasm.begin_function(m_name, arglist, returntype, False,
                                     'virtual')  #, 'abstract')
                ilasm.add_comment('abstract method')
                if isinstance(METH.RESULT, ootype.OOType):
                    ilasm.opcode('ldnull')
                else:
                    push_constant(self.db, METH.RESULT, 0, self.gen)
                ilasm.opcode('ret')
                ilasm.end_function()

        ilasm.end_class()

        if self.namespace:
            ilasm.end_namespace()
Beispiel #16
0
 def simple_call(self, *s_args):
     from pypy.translator.cli.query import get_cli_class
     DELEGATE = get_cli_class('System.Delegate')._INSTANCE
     if ootype.isSubclass(self.ootype, DELEGATE):
         s_invoke = self.getattr(immutablevalue('Invoke'))
         return s_invoke.simple_call(*s_args)
     else:
         # cannot call a non-delegate
         return SomeObject.simple_call(self, *s_args)
Beispiel #17
0
 def simple_call(self, *s_args):
     from pypy.translator.cli.query import get_cli_class
     DELEGATE = get_cli_class('System.Delegate')._INSTANCE
     if ootype.isSubclass(self.ootype, DELEGATE):
         s_invoke = self.getattr(immutablevalue('Invoke'))
         return s_invoke.simple_call(*s_args)
     else:
         # cannot call a non-delegate
         return SomeObject.simple_call(self, *s_args)
Beispiel #18
0
    def _translate_instance(self, OOTYPE):
        assert isinstance(OOTYPE, ootype.Instance)
        assert OOTYPE is not ootype.ROOT

        # Create class object if it does not already exist:
        if OOTYPE in self._classes:
            return self._classes[OOTYPE]

        # Create the class object first
        clsnm = self._pkg(self._uniq(OOTYPE._name))
        clsobj = node.Class(clsnm)
        self._classes[OOTYPE] = clsobj

        # Resolve super class 
        assert OOTYPE._superclass
        supercls = self._translate_superclass_of(OOTYPE)
        clsobj.set_super_class(supercls)

        # TODO --- mangle field and method names?  Must be
        # deterministic, or use hashtable to avoid conflicts between
        # classes?
        
        # Add fields:
        self._translate_class_fields(clsobj, OOTYPE)
            
        # Add methods:
        for mname, mimpl in OOTYPE._methods.iteritems():
            if not hasattr(mimpl, 'graph'):
                # Abstract method
                METH = mimpl._TYPE
                arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS
                           if ARG is not ootype.Void]
                returntype = self.lltype_to_cts(METH.RESULT)
                clsobj.add_abstract_method(jvm.Method.v(
                    clsobj, mname, arglist, returntype))
            else:
                # if the first argument's type is not a supertype of
                # this class it means that this method this method is
                # not really used by the class: don't render it, else
                # there would be a type mismatch.
                args =  mimpl.graph.getargs()
                SELF = args[0].concretetype
                if not ootype.isSubclass(OOTYPE, SELF): continue
                mobj = self._function_for_graph(
                    clsobj, mname, False, mimpl.graph)
                graphs = OOTYPE._lookup_graphs(mname)
                if len(graphs) == 1:
                    mobj.is_final = True
                clsobj.add_method(mobj)

        # currently, we always include a special "dump" method for debugging
        # purposes
        dump_method = node.InstanceDumpMethod(self, OOTYPE, clsobj)
        clsobj.add_method(dump_method)

        self.pending_node(clsobj)
        return clsobj
Beispiel #19
0
    def render(self, ilasm):        
        if self.is_root(self.INSTANCE):
            return

        self.ilasm = ilasm
        self.gen = CLIBaseGenerator(self.db, ilasm)

        if self.namespace:
            ilasm.begin_namespace(self.namespace)

        ilasm.begin_class(self.name, self.get_base_class(), abstract=self.is_abstract())
        for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems():
            cts_type = self.cts.lltype_to_cts(f_type)
            f_name = self.cts.escape_name(f_name)
            if cts_type != CTS.types.void:
                ilasm.field(f_name, cts_type)

        self._ctor()
        self._toString()

        for m_name, m_meth in self.INSTANCE._methods.iteritems():
            if hasattr(m_meth, 'graph'):
                # if the first argument's type is not a supertype of
                # this class it means that this method this method is
                # not really used by the class: don't render it, else
                # there would be a type mismatch.
                args =  m_meth.graph.getargs()
                SELF = args[0].concretetype
                if not ootype.isSubclass(self.INSTANCE, SELF):
                    continue
                f = self.db.genoo.Function(self.db, m_meth.graph, m_name, is_method = True)
                f.render(ilasm)
            else:
                # abstract method
                METH = m_meth._TYPE
                arglist = [(self.cts.lltype_to_cts(ARG), 'v%d' % i)
                           for i, ARG in enumerate(METH.ARGS)
                           if ARG is not ootype.Void]
                returntype = self.cts.lltype_to_cts(METH.RESULT)
                ilasm.begin_function(m_name, arglist, returntype, False, 'virtual') #, 'abstract')
                ilasm.add_comment('abstract method')
                if isinstance(METH.RESULT, ootype.OOType):
                    ilasm.opcode('ldnull')
                else:
                    push_constant(self.db, METH.RESULT, 0, self.gen)
                ilasm.opcode('ret')
                ilasm.end_function()

        ilasm.end_class()

        if self.namespace:
            ilasm.end_namespace()
Beispiel #20
0
class __extend__(pairtype(SomeOOInstance, SomeInteger)):
    def getitem((ooinst, index)):
        if ooinst.ootype._isArray:
            return SomeOOInstance(ooinst.ootype._ELEMENT)
        return s_ImpossibleValue

    def setitem((ooinst, index), s_value):
        if ooinst.ootype._isArray:
            if s_value is annmodel.s_None:
                return s_None
            ELEMENT = ooinst.ootype._ELEMENT
            VALUE = s_value.ootype
            assert ootype.isSubclass(VALUE, ELEMENT)
            return s_None
        return s_ImpossibleValue
Beispiel #21
0
def oodowncast(I, i):
    assert isinstance(I.const, ootype.Instance)
    if ootype.isSubclass(I.const, i.ootype):
        return SomeOOInstance(I.const)
    else:
        raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
Beispiel #22
0
def oodowncast(I, i):
    assert isinstance(I.const, ootype.Instance)
    if ootype.isSubclass(I.const, i.ootype):
        return SomeOOInstance(I.const)
    else:
        raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
Beispiel #23
0
 def is_exception_instance(self, INSTANCE):
     return ootype.isSubclass(INSTANCE, self._EXCEPTION_INST)
Beispiel #24
0
 def is_exception_instance(self, INSTANCE):
     return ootype.isSubclass(INSTANCE, self._EXCEPTION_INST)
Beispiel #25
0
 def castable(self, TO, var):
     return ootype.isSubclass(lltype.typeOf(var), TO)