[pypy-svn] r25522 - in pypy/dist/pypy/rpython: . lltypesystem test

arigo at codespeak.net arigo at codespeak.net
Fri Apr 7 20:32:09 CEST 2006


Author: arigo
Date: Fri Apr  7 20:32:07 2006
New Revision: 25522

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/normalizecalls.py
   pypy/dist/pypy/rpython/test/test_normalizecalls.py
Log:
(arre, arigo)

Turned the class range ids into ComputedIntSymbolics.
Added a test that shows that mix-level helpers can now
add subclasses of existing classes.



Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Fri Apr  7 20:32:07 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck, r_longlong, r_ulonglong
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.objectmodel import ComputedIntSymbolic
 
 import sys
 import math
@@ -181,6 +182,8 @@
             val = varorconst.value
         except AttributeError:
             val = self.bindings[varorconst]
+        if isinstance(val, ComputedIntSymbolic):
+            val = val.compute_fn()
         if varorconst.concretetype is not lltype.Void:
             try:
                 val = lltype.enforce(varorconst.concretetype, val)

Modified: pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py	Fri Apr  7 20:32:07 2006
@@ -31,14 +31,15 @@
     v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
     if isinstance(v_cls, Constant):
         cls = v_cls.value
-        if cls.subclassrange_max == cls.subclassrange_min + 1:
-            # a class with no subclass
-            return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls)
-        else:
-            minid = hop.inputconst(lltype.Signed, cls.subclassrange_min)
-            maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max)
-            return hop.gendirectcall(rclass.ll_isinstance_const, v_obj, minid,
-                                     maxid)
+        # XXX re-implement the following optimization
+        #if cls.subclassrange_max == cls.subclassrange_min + 1:
+        #    # a class with no subclass
+        #    return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls)
+        #else:
+        minid = hop.inputconst(lltype.Signed, cls.subclassrange_min)
+        maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max)
+        return hop.gendirectcall(rclass.ll_isinstance_const, v_obj, minid,
+                                 maxid)
     else:
         return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri Apr  7 20:32:07 2006
@@ -266,14 +266,15 @@
         v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
         if isinstance(v_cls2, Constant):
             cls2 = v_cls2.value
-            if cls2.subclassrange_max == cls2.subclassrange_min + 1:
-                # a class with no subclass
-                return hop.genop('ptr_eq', [v_cls1, v_cls2], resulttype=Bool)
-            else:
-                minid = hop.inputconst(Signed, cls2.subclassrange_min)
-                maxid = hop.inputconst(Signed, cls2.subclassrange_max)
-                return hop.gendirectcall(ll_issubclass_const, v_cls1, minid,
-                                         maxid)
+            # XXX re-implement the following optimization
+##            if cls2.subclassrange_max == cls2.subclassrange_min + 1:
+##                # a class with no subclass
+##                return hop.genop('ptr_eq', [v_cls1, v_cls2], resulttype=Bool)
+##            else:
+            minid = hop.inputconst(Signed, cls2.subclassrange_min)
+            maxid = hop.inputconst(Signed, cls2.subclassrange_max)
+            return hop.gendirectcall(ll_issubclass_const, v_cls1, minid,
+                                     maxid)
         else:
             v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr)
             return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2)

Modified: pypy/dist/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/normalizecalls.py	Fri Apr  7 20:32:07 2006
@@ -9,7 +9,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import needsgc
-from pypy.rpython.objectmodel import instantiate
+from pypy.rpython.objectmodel import instantiate, ComputedIntSymbolic
 
 def normalize_call_familes(annotator):
     for callfamily in annotator.bookkeeper.pbc_maximal_call_families.infos():
@@ -274,8 +274,26 @@
 
 # ____________________________________________________________
 
-def assign_inheritance_ids(annotator):
+class MinIdSymbolic(ComputedIntSymbolic):
+    def __init__(self, classdef):
+        self.classdef = classdef
+    def compute_fn(self):
+        if self.classdef.minid is self:
+            compute_inheritance_ids(self.classdef.bookkeeper)
+        return self.classdef.minid
+
+class MaxIdSymbolic(ComputedIntSymbolic):
+    def __init__(self, classdef):
+        self.classdef = classdef
+    def compute_fn(self):
+        if self.classdef.maxid is self:
+            compute_inheritance_ids(self.classdef.bookkeeper)
+        return self.classdef.maxid
+
+def compute_inheritance_ids(bookkeeper):
     def assign_id(classdef, nextid):
+        assert isinstance(classdef.minid, MinIdSymbolic)
+        assert isinstance(classdef.maxid, MaxIdSymbolic)
         classdef.minid = nextid
         nextid += 1
         for subclass in classdef.subdefs:
@@ -283,11 +301,16 @@
         classdef.maxid = nextid
         return classdef.maxid
     id_ = 0
-    for classdef in annotator.bookkeeper.classdefs:
+    for classdef in bookkeeper.classdefs:
         if classdef.basedef is None:
-            prevmaxid = getattr(classdef, 'maxid', sys.maxint)
             id_ = assign_id(classdef, id_)
-            assert id_ <= prevmaxid, "non-orthogonal class hierarchy growth"
+
+def assign_inheritance_ids(annotator):
+    for classdef in annotator.bookkeeper.classdefs:
+        if not hasattr(classdef, 'minid'):
+            classdef.minid = MinIdSymbolic(classdef)
+        if not hasattr(classdef, 'maxid'):
+            classdef.maxid = MaxIdSymbolic(classdef)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rpython/test/test_normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_normalizecalls.py	(original)
+++ pypy/dist/pypy/rpython/test/test_normalizecalls.py	Fri Apr  7 20:32:07 2006
@@ -144,25 +144,27 @@
         res = llinterp.eval_graph(graphof(translator, dummyfn), [2])
         assert res == -2
 
+
+class PBase:
+    def fn(self):
+        raise NotImplementedError
+class PSub1(PBase):
+    def fn(self):
+        return 1
+class PSub2(PBase):
+    def fn(self):
+        return 2
+def prefn(n):
+    if n == 1:
+        x = PSub1()
+    else:
+        x = PSub2()
+    return x.fn() * 100 + isinstance(x, PSub2)
+
+
 class TestNormalizeAfterTheFact(TestNormalize):
 
     def rtype(self, fn, argtypes, resulttype):
-        class Base:
-            def fn(self):
-                raise NotImplementedError
-        class Sub1(Base):
-            def fn(self):
-                return 1
-        class Sub2(Base):
-            def fn(self):
-                return 2
-        def prefn(n):
-            if n == 1:
-                x = Sub1()
-            else:
-                x = Sub2()
-            return x.fn()
-        
         t = TranslationContext()
         a = t.buildannotator()
         a.build_types(prefn, [int])
@@ -182,9 +184,9 @@
         # sanity check prefn
         llinterp = LLInterpreter(typer)
         res = llinterp.eval_graph(graphof(t, prefn), [1])
-        assert res == 1
+        assert res == 100
         res = llinterp.eval_graph(graphof(t, prefn), [2])
-        assert res == 2
+        assert res == 201
 
         t.checkgraphs()
         return t
@@ -211,3 +213,24 @@
         graph = annhelper.getgraph(f, [], annmodel.SomeInteger())
         annhelper.finish()
         
+    def test_add_more_subclasses(self):
+        class Sub3(PBase):
+            def newmethod(self):
+                return 3
+        def dummyfn(n):
+            x = Sub3()
+            return x.newmethod()
+
+        translator = self.rtype(dummyfn, [int], int)
+        base_graph    = graphof(translator, PBase.fn.im_func)
+        sub1_graph    = graphof(translator, PSub1.fn.im_func)
+        sub2_graph    = graphof(translator, PSub2.fn.im_func)
+        sub3_graph    = graphof(translator, Sub3.fn.im_func)
+        dummyfn_graph = graphof(translator, dummyfn)
+        assert base_graph.getreturnvar().concretetype == lltype.Signed
+        assert sub1_graph.getreturnvar().concretetype == lltype.Signed
+        assert sub2_graph.getreturnvar().concretetype == lltype.Signed
+        assert sub3_graph.getreturnvar().concretetype == lltype.Signed
+        assert dummyfn_graph.getreturnvar().concretetype == lltype.Signed
+
+        



More information about the Pypy-commit mailing list