[pypy-svn] r40729 - in pypy/dist/pypy: annotation rlib rpython rpython/lltypesystem rpython/lltypesystem/test

arigo at codespeak.net arigo at codespeak.net
Sun Mar 18 22:25:46 CET 2007


Author: arigo
Date: Sun Mar 18 22:25:41 2007
New Revision: 40729

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/classdef.py
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/specialize.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rlib/objectmodel.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/lltypesystem/rtagged.py
   pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rvirtualizable.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rpbc.py
Log:
(pedronis, arigo)

- added general support for flags on SomeInstance.
- the access_directly flag on SomeInstance: used for virtualizables,
  to mean that it's safe to access the fields directly (i.e. at this
  point the virtualizable is not actually virtualized).
- obscure specialization logic to make two copies of functions
  automatically: one in which at least one argument has the 
  'access_directly' flag, and one in which none has.

Motivation: see next check-in.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Sun Mar 18 22:25:41 2007
@@ -617,7 +617,15 @@
             if basedef is None:
                 # print warning?
                 return SomeObject()
-        return SomeInstance(basedef, can_be_None=ins1.can_be_None or ins2.can_be_None)
+        flags = ins1.flags
+        if flags:
+            flags = flags.copy()
+            for key, value in flags.items():
+                if key not in ins2.flags or ins2.flags[key] != value:
+                    del flags[key]
+        return SomeInstance(basedef,
+                            can_be_None=ins1.can_be_None or ins2.can_be_None,
+                            flags=flags)
 
     def improve((ins1, ins2)):
         if ins1.classdef is None:

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Sun Mar 18 22:25:41 2007
@@ -519,13 +519,16 @@
             self.pbctypes[cls] = True
         return result
 
-    def getmethoddesc(self, funcdesc, originclassdef, selfclassdef, name):
-        key = funcdesc, originclassdef, selfclassdef, name
+    def getmethoddesc(self, funcdesc, originclassdef, selfclassdef, name,
+                      flags={}):
+        flagskey = flags.items()
+        flagskey.sort()
+        key = funcdesc, originclassdef, selfclassdef, name, tuple(flagskey)
         try:
             return self.methoddescs[key]
         except KeyError:
             result = description.MethodDesc(self, funcdesc, originclassdef,
-                                            selfclassdef, name)
+                                            selfclassdef, name, flags)
             self.methoddescs[key] = result
             return result
 

Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Sun Mar 18 22:25:41 2007
@@ -10,7 +10,7 @@
 from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
 from pypy.annotation.model import SomeExternalObject
 from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
-from pypy.annotation.model import add_knowntypedata, not_const
+from pypy.annotation.model import add_knowntypedata
 from pypy.annotation.model import s_ImpossibleValue
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation import description
@@ -319,9 +319,6 @@
 def robjmodel_keepalive_until_here(*args_s):
     return immutablevalue(None)
 
-def robjmodel_hint(s, **kwds_s):
-    return not_const(s)
-
 def llmemory_cast_ptr_to_adr(s):
     return SomeAddress()
 
@@ -383,7 +380,6 @@
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.r_dict] = robjmodel_r_dict
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.hlinvoke] = robjmodel_hlinvoke
 BUILTIN_ANALYZERS[pypy.rlib.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here
-BUILTIN_ANALYZERS[pypy.rlib.objectmodel.hint] = robjmodel_hint
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int

Modified: pypy/dist/pypy/annotation/classdef.py
==============================================================================
--- pypy/dist/pypy/annotation/classdef.py	(original)
+++ pypy/dist/pypy/annotation/classdef.py	Sun Mar 18 22:25:41 2007
@@ -333,7 +333,7 @@
                     return None
         return None
 
-    def lookup_filter(self, pbc, name=None):
+    def lookup_filter(self, pbc, name=None, flags={}):
         """Selects the methods in the pbc that could possibly be seen by
         a lookup performed on an instance of 'self', removing the ones
         that cannot appear.
@@ -365,10 +365,10 @@
                     continue # not matching
                 # bind the method by giving it a selfclassdef.  Use the
                 # more precise subclass that it's coming from.
-                desc = desc.bind_self(methclassdef)
+                desc = desc.bind_self(methclassdef, flags)
             d.append(desc)
         if uplookup is not None:            
-            d.append(updesc.bind_self(self))
+            d.append(updesc.bind_self(self, flags))
 
         if d or pbc.can_be_None:
             return SomePBC(d, can_be_None=pbc.can_be_None)

Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Sun Mar 18 22:25:41 2007
@@ -676,12 +676,13 @@
     knowntype = types.MethodType
 
     def __init__(self, bookkeeper, funcdesc, originclassdef, 
-                 selfclassdef, name):
+                 selfclassdef, name, flags={}):
         super(MethodDesc, self).__init__(bookkeeper)
         self.funcdesc = funcdesc
         self.originclassdef = originclassdef
         self.selfclassdef = selfclassdef
         self.name = name
+        self.flags = flags
 
     def __repr__(self):
         if self.selfclassdef is None:
@@ -696,7 +697,7 @@
         from pypy.annotation.model import SomeInstance
         if self.selfclassdef is None:
             raise Exception("calling %r" % (self,))
-        s_instance = SomeInstance(self.selfclassdef)
+        s_instance = SomeInstance(self.selfclassdef, flags = self.flags)
         args = args.prepend(s_instance)
         return self.funcdesc.pycall(schedule, args, s_previous_result)
 
@@ -704,12 +705,13 @@
         self.bookkeeper.warning("rebinding an already bound %r" % (self,))
         return self.funcdesc.bind_under(classdef, name)
 
-    def bind_self(self, newselfclassdef):
+    def bind_self(self, newselfclassdef, flags={}):
         return self.bookkeeper.getmethoddesc(self.funcdesc,
                                              self.originclassdef,
                                              newselfclassdef,
-                                             self.name)
-    
+                                             self.name,
+                                             flags)
+
     def consider_call_site(bookkeeper, family, descs, args, s_result):
         shape = rawshape(args, nextra=1)     # account for the extra 'self'
         funcdescs = [methoddesc.funcdesc for methoddesc in descs]

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Sun Mar 18 22:25:41 2007
@@ -297,10 +297,11 @@
 class SomeInstance(SomeObject):
     "Stands for an instance of a (user-defined) class."
 
-    def __init__(self, classdef, can_be_None=False):
+    def __init__(self, classdef, can_be_None=False, flags={}):
         self.classdef = classdef
         self.knowntype = classdef or object
         self.can_be_None = can_be_None
+        self.flags = flags
 
     def fmt_knowntype(self, kt):
         return None
@@ -309,6 +310,11 @@
             return 'object'
         else:
             return cdef.name
+    def fmt_flags(self, flags):
+        if flags:
+            return repr(flags)
+        else:
+            return None
 
     def can_be_none(self):
         return self.can_be_None

Modified: pypy/dist/pypy/annotation/specialize.py
==============================================================================
--- pypy/dist/pypy/annotation/specialize.py	(original)
+++ pypy/dist/pypy/annotation/specialize.py	Sun Mar 18 22:25:41 2007
@@ -6,12 +6,12 @@
 from pypy.tool.algo.unionfind import UnionFind
 from pypy.objspace.flow.model import Block, Link, Variable, SpaceOperation
 from pypy.objspace.flow.model import Constant, checkgraph
+from pypy.annotation import model as annmodel
 
 def default_specialize(funcdesc, args_s):
     argnames, vararg, kwarg = funcdesc.signature
     assert not kwarg, "functions with ** arguments are not supported"
     if vararg:
-        from pypy.annotation import model as annmodel
         # calls to *arg functions: create one version per number of args
         assert len(args_s) == len(argnames) + 1
         s_tuple = args_s[-1]
@@ -20,6 +20,8 @@
         s_len = s_tuple.len()
         assert s_len.is_constant(), "calls require known number of args"
         nb_extra_args = s_len.const
+        flattened_s = list(args_s[:-1])
+        flattened_s.extend(s_tuple.items)
         
         def builder(translator, func):
             # build a hacked graph that doesn't take a *arg any more, but
@@ -46,13 +48,42 @@
                 graph.defaults = None   # shouldn't be used in this case
             checkgraph(graph)
             return graph
-        
-        return funcdesc.cachedgraph(nb_extra_args,
-                                    alt_name='%s_star%d' % (funcdesc.name,
-                                                            nb_extra_args),
+
+        key, name_suffix = access_direct_key(nb_extra_args, flattened_s)
+        return funcdesc.cachedgraph(key,
+                                    alt_name='%s_star%d%s' % (funcdesc.name,
+                                                              nb_extra_args,
+                                                              name_suffix),
                                     builder=builder)
     else:
-        return funcdesc.cachedgraph(None)
+        key, name_suffix = access_direct_key(None, args_s)
+        if name_suffix:
+            alt_name = '%s%s' % (funcdesc.name, name_suffix)
+        else:
+            alt_name = None
+        return funcdesc.cachedgraph(key, alt_name=alt_name)
+
+def access_direct_key(key, args_s):
+    for s_obj in args_s:
+        if (isinstance(s_obj, annmodel.SomeInstance) and
+            'access_directly' in s_obj.flags):
+            return (AccessDirect, key), '_AccessDirect'
+    return key, ''
+
+class AccessDirect(object):
+    """marker for specialization: set when any arguments is a SomeInstance
+    which has the 'access_directly' flag set."""
+
+def getuniquenondirectgraph(desc):
+    result = []
+    for key, graph in desc._cache.items():
+        if (type(key) is tuple and len(key) == 2 and
+            key[0] is AccessDirect):
+            continue
+        result.append(graph)
+    assert len(result) == 1
+    return result[0]
+        
 
 # ____________________________________________________________________________
 # specializations

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Sun Mar 18 22:25:41 2007
@@ -524,7 +524,8 @@
             #       that can't possibly apply to an instance of ins.classdef.
             # XXX do it more nicely
             if isinstance(s_result, SomePBC):
-                s_result = ins.classdef.lookup_filter(s_result, attr)
+                s_result = ins.classdef.lookup_filter(s_result, attr,
+                                                      ins.flags)
             elif isinstance(s_result, SomeImpossibleValue):
                 ins.classdef.check_missing_attribute_update(attr)
                 # blocking is harmless if the attribute is explicitly listed

Modified: pypy/dist/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rlib/objectmodel.py	(original)
+++ pypy/dist/pypy/rlib/objectmodel.py	Sun Mar 18 22:25:41 2007
@@ -192,6 +192,42 @@
 def hint(x, **kwds):
     return x
 
+class Entry(ExtRegistryEntry):
+    _about_ = hint
+
+    def compute_result_annotation(self, s_x, **kwds_s):
+        from pypy.annotation import model as annmodel
+        s_x = annmodel.not_const(s_x)
+        if 's_access_directly' in kwds_s:
+            if isinstance(s_x, annmodel.SomeInstance):
+                from pypy.objspace.flow.model import Constant
+                classdesc = s_x.classdef.classdesc
+                virtualizable = classdesc.read_attribute('_virtualizable_',
+                                                         Constant(False)).value
+                if virtualizable:
+                    flags = s_x.flags.copy()
+                    flags['access_directly'] = True
+                    s_x = annmodel.SomeInstance(s_x.classdef,
+                                                s_x.can_be_None,
+                                                flags)
+        return s_x
+
+    def specialize_call(self, hop, **kwds_i):
+        from pypy.rpython.lltypesystem import lltype
+        hints = {}
+        for key, index in kwds_i.items():
+            s_value = hop.args_s[index]
+            if not s_value.is_constant():
+                from pypy.rpython.error import TyperError
+                raise TyperError("hint %r is not constant" % (key,))
+            assert key.startswith('i_')
+            hints[key[2:]] = s_value.const
+        v = hop.inputarg(hop.args_r[0], arg=0)
+        c_hint = hop.inputconst(lltype.Void, hints)
+        hop.exception_cannot_occur()
+        return hop.genop('hint', [v, c_hint], resulttype=v.concretetype)
+
+
 def we_are_jitted():
     return False
 # timeshifts to True

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Sun Mar 18 22:25:41 2007
@@ -469,7 +469,7 @@
                 raise MissingRTypeAttribute(attr)
             return self.rbase.getfieldrepr(attr)
 
-    def getfield(self, vinst, attr, llops, force_cast=False):
+    def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
         """Read the given attribute (or __class__ for the type) of 'vinst'."""
         if attr in self.fields:
             mangled_name, r = self.fields[attr]
@@ -480,9 +480,11 @@
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
-            return self.rbase.getfield(vinst, attr, llops, force_cast=True)
+            return self.rbase.getfield(vinst, attr, llops, force_cast=True,
+                                       flags=flags)
 
-    def setfield(self, vinst, attr, vvalue, llops, force_cast=False, opname='setfield'):
+    def setfield(self, vinst, attr, vvalue, llops, force_cast=False,
+                 opname='setfield', flags={}):
         """Write the given attribute (or __class__ for the type) of 'vinst'."""
         if attr in self.fields:
             mangled_name, r = self.fields[attr]
@@ -494,7 +496,8 @@
         else:
             if self.classdef is None:
                 raise MissingRTypeAttribute(attr)
-            self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True, opname=opname)
+            self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True,
+                                opname=opname, flags=flags)
 
     def new_instance(self, llops, classcallhop=None, v_cpytype=None):
         """Build a new instance, without calling __init__."""
@@ -533,8 +536,8 @@
                 if value is not None:
                     cvalue = inputconst(r.lowleveltype,
                                         r.convert_desc_or_const(value))
-                    self.setfield(vptr, fldname, cvalue, llops)
-
+                    self.setfield(vptr, fldname, cvalue, llops,
+                                  {'access_directly': True})
         return vptr
 
     def rtype_type(self, hop):
@@ -555,7 +558,8 @@
             [desc] = hop.s_result.descriptions
             return hop.inputconst(Void, desc.pyobj)
         if attr in self.allinstancefields:
-            return self.getfield(vinst, attr, hop.llops)
+            return self.getfield(vinst, attr, hop.llops,
+                                 flags=hop.args_s[0].flags)
         elif attr in self.rclass.allmethods:
             # special case for methods: represented as their 'self' only
             # (see MethodsPBCRepr)
@@ -569,7 +573,8 @@
         attr = hop.args_s[1].const
         r_value = self.getfieldrepr(attr)
         vinst, vattr, vvalue = hop.inputargs(self, Void, r_value)
-        self.setfield(vinst, attr, vvalue, hop.llops)
+        self.setfield(vinst, attr, vvalue, hop.llops,
+                      flags=hop.args_s[0].flags)
 
     def rtype_is_true(self, hop):
         vinst, = hop.inputargs(self)

Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rtagged.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py	Sun Mar 18 22:25:41 2007
@@ -90,7 +90,7 @@
         else:
             return cunboxedcls
 
-    def getfield(self, vinst, attr, llops, force_cast=False):
+    def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
         if not self.is_parent and attr == self.specialfieldname:
             return self.getvalue_from_unboxed(llops, vinst)
         elif attr == '__class__':

Modified: pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py	Sun Mar 18 22:25:41 2007
@@ -126,9 +126,10 @@
         return ll_setter
    
 
-    def getfield(self, vinst, attr, llops, force_cast=False):
+    def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
         """Read the given attribute (or __class__ for the type) of 'vinst'."""
-        if attr in self.my_redirected_fields:
+        if (attr in self.my_redirected_fields
+            and not flags.get('access_directly')):
             mangled_name, r = self.fields[attr]
             if force_cast:
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
@@ -137,9 +138,11 @@
         else:
             return InstanceRepr.getfield(self, vinst, attr, llops, force_cast)
 
-    def setfield(self, vinst, attr, vvalue, llops, force_cast=False, opname='setfield'):
+    def setfield(self, vinst, attr, vvalue, llops, force_cast=False,
+                 opname='setfield', flags={}):
         """Write the given attribute (or __class__ for the type) of 'vinst'."""
-        if attr in self.my_redirected_fields:
+        if (attr in self.my_redirected_fields
+            and not flags.get('access_directly')):
             mangled_name, r = self.fields[attr]
             if force_cast:
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rvirtualizable.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rvirtualizable.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rvirtualizable.py	Sun Mar 18 22:25:41 2007
@@ -1,6 +1,8 @@
 import py
+from pypy.objspace.flow.model import summary
+from pypy.rlib.objectmodel import hint
 from pypy.rpython.lltypesystem import lltype, rclass
-from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.test.test_llinterp import interpret, get_interpreter
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 from pypy.rpython.error import TyperError
 
@@ -200,3 +202,95 @@
     res = interpret(f, [42])
     assert res.item1 == 42
     
+
+def test_access_directly():
+    def g(b):
+        return b.v0
+
+    def f(n):
+        b = B(n)
+        b = hint(b, access_directly=True)
+        return g(b)
+
+    interp, graph = get_interpreter(f, [23])
+    g_graph = interp.typer.annotator.translator._graphof(g)
+    assert summary(g_graph) == {'getfield': 1}
+
+    res = interp.eval_graph(graph, [23])
+    assert res == 23
+
+
+def test_access_directly_specialized():
+    def g(b):
+        return b.v0
+
+    def f(n):
+        b = B(n)
+        x = g(b)
+        y = g(hint(b, access_directly=True))
+        return x + y
+
+    interp, graph = get_interpreter(f, [23])
+    desc = interp.typer.annotator.bookkeeper.getdesc(g)
+    g_graphs = desc._cache.values()
+    assert len(g_graphs) == 2
+    summaries = map(summary, g_graphs)
+    summaries.sort()
+    assert summaries == [{'direct_call': 1},
+                         {'getfield': 1}]
+
+    res = interp.eval_graph(graph, [23])
+    assert res == 46
+
+
+def test_access_directly_escape():
+    class Global:
+        pass
+    glob = Global()
+
+    def g(b):
+        glob.b = b
+
+    def h(b):
+        return b.v0
+
+    def f(n):
+        b = B(n)
+        g(b)
+        g(hint(b, access_directly=True))
+        return h(glob.b)
+
+    interp, graph = get_interpreter(f, [23])
+    desc = interp.typer.annotator.bookkeeper.getdesc(g)
+    g_graphs = desc._cache.values()
+    assert len(g_graphs) == 2
+    summaries = map(summary, g_graphs)
+    summaries.sort()
+    assert summaries == [{'setfield': 1},
+                         {'setfield': 1}]
+    h_graph = interp.typer.annotator.translator._graphof(h)
+    assert summary(h_graph) == {'direct_call': 1}
+
+    res = interp.eval_graph(graph, [23])
+    assert res == 23
+
+
+def test_access_directly_method():
+    class A(B):
+        def meth1(self, x):
+            return self.g(x+1)
+
+        def g(self, y):
+            return self.v0 * y
+
+    def f(n):
+        a = A(n)
+        a = hint(a, access_directly=True)
+        return a.meth1(100)
+
+    interp, graph = get_interpreter(f, [23])
+    g_graph = interp.typer.annotator.translator._graphof(A.g.im_func)
+    assert summary(g_graph) == {'getfield': 1, 'int_mul': 1}
+
+    res = interp.eval_graph(graph, [23])
+    assert res == 2323

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Sun Mar 18 22:25:41 2007
@@ -616,23 +616,6 @@
 
 BUILTIN_TYPER[objectmodel.keepalive_until_here] = rtype_keepalive_until_here
 
-# hint
-
-def rtype_hint(hop, **kwds_i):
-    hints = {}
-    for key, index in kwds_i.items():
-        s_value = hop.args_s[index]
-        if not s_value.is_constant():
-            raise TyperError("hint %r is not constant" % (key,))
-        assert key.startswith('i_')
-        hints[key[2:]] = s_value.const
-    v = hop.inputarg(hop.args_r[0], arg=0)
-    c_hint = hop.inputconst(lltype.Void, hints)
-    hop.exception_cannot_occur()
-    return hop.genop('hint', [v, c_hint], resulttype=v.concretetype)
-
-BUILTIN_TYPER[objectmodel.hint] = rtype_hint
-
 def rtype_cast_ptr_to_adr(hop):
     vlist = hop.inputargs(hop.args_r[0])
     assert isinstance(vlist[0].concretetype, lltype.Ptr)

Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py	(original)
+++ pypy/dist/pypy/rpython/rpbc.py	Sun Mar 18 22:25:41 2007
@@ -806,11 +806,15 @@
         mdescs = s_pbc.descriptions.keys()
         methodname = mdescs[0].name
         classdef = mdescs[0].selfclassdef
+        flags    = mdescs[0].flags
         for mdesc in mdescs[1:]:
             if mdesc.name != methodname:
                 raise TyperError("cannot find a unique name under which the "
                                  "methods can be found: %r" % (
                         mdescs,))
+            if mdesc.flags != flags:
+                raise TyperError("inconsistent 'flags': %r versus %r" % (
+                    mdesc.flags, flags))
             classdef = classdef.commonbase(mdesc.selfclassdef)
             if classdef is None:
                 raise TyperError("mixing methods coming from instances of "
@@ -819,7 +823,7 @@
         self.methodname = methodname
         self.classdef = classdef.locate_attribute(methodname)
         # the low-level representation is just the bound 'self' argument.
-        self.s_im_self = annmodel.SomeInstance(self.classdef)
+        self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags)
         self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef)
         self.lowleveltype = self.r_im_self.lowleveltype
 



More information about the Pypy-commit mailing list