[pypy-svn] r24518 - in pypy/dist/pypy/jit: . test

arigo at codespeak.net arigo at codespeak.net
Fri Mar 17 14:35:33 CET 2006


Author: arigo
Date: Fri Mar 17 14:35:31 2006
New Revision: 24518

Modified:
   pypy/dist/pypy/jit/hintcontainer.py
   pypy/dist/pypy/jit/hintmodel.py
   pypy/dist/pypy/jit/test/test_hint_annotation.py
Log:
hintannotator: detect mixing of incompatible virtual container types
and fall back by setting a "degenerated" flag on the ContainerDef.
The hintrtyper should detect this flag.


Modified: pypy/dist/pypy/jit/hintcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/hintcontainer.py	(original)
+++ pypy/dist/pypy/jit/hintcontainer.py	Fri Mar 17 14:35:31 2006
@@ -12,6 +12,12 @@
     def __init__(self, bookkeeper, TYPE):
         self.T = TYPE
         self.bookkeeper = bookkeeper
+        # if a virtual container "escapes" control in some way, e.g. by
+        # being unified with a SomeLLAbstractVariable, the ContainerDef
+        # becomes 'degenerated'.  For the hintrtyper, degenerated
+        # SomeLLAbstractContainers should roughly be equivalent to
+        # SomeLLAbstractVariables.
+        self.degenerated = False
         # hack to try to produce a repr that shows identifications
         key = (self.__class__, TYPE)
         weakdict = AbstractContainerDef.__cache.setdefault(key,
@@ -47,6 +53,14 @@
         hs_c.const = TYPE._defl()
         return hs_c
 
+def degenerate_item(item, ITEM_TYPE):
+    if isinstance(ITEM_TYPE, lltype.ContainerType):
+        hs = item.s_value
+        assert isinstance(hs, hintmodel.SomeLLAbstractContainer)
+        hs.contentdef.mark_degenerated()
+    else:
+        item.generalize(hintmodel.SomeLLAbstractVariable(ITEM_TYPE))
+
 # ____________________________________________________________
 
 class FieldValue(ListItem):
@@ -99,15 +113,37 @@
         return self.fields == other.fields
 
     def union(self, other):
-        # xxx about vparent?
         assert self.T == other.T
         for name in self.names:
             self.fields[name].merge(other.fields[name])
+        incompatible = False
+        if self.vparent is not None:
+            if other.vparent is not None:
+                if self.vparent.T != other.vparent.T:
+                    incompatible = True
+                else:
+                    self.vparent.union(other.vparent)
+            else:
+                incompatible = True
+        elif other.vparent is not None:
+            incompatible = True
+        if incompatible or self.degenerated or other.degenerated:
+            self.mark_degenerated()
+            other.mark_degenerated()
         return self
 
     def generalize_field(self, name, hs_value):
         self.fields[name].generalize(hs_value)
 
+    def mark_degenerated(self):
+        if self.degenerated:
+            return
+        self.degenerated = True
+        for name in self.names:
+            degenerate_item(self.fields[name], self.fieldtype(name))
+        if self.vparent is not None:
+            self.vparent.mark_degenerated()
+
 # ____________________________________________________________
 
 
@@ -140,3 +176,7 @@
 
     def generalize_item(self, hs_value):
         self.arrayitem.generalize(hs_value)
+
+    def mark_degenerated(self):
+        self.degenerated = True
+        degenerate_item(self.arrayitem, self.T.OF)

Modified: pypy/dist/pypy/jit/hintmodel.py
==============================================================================
--- pypy/dist/pypy/jit/hintmodel.py	(original)
+++ pypy/dist/pypy/jit/hintmodel.py	Fri Mar 17 14:35:31 2006
@@ -151,6 +151,14 @@
         if hs_flags.const.get('forget', False):
             XXX    # not implemented
 
+    def getfield(hs_v1, hs_fieldname):
+        S = hs_v1.concretetype.TO
+        FIELD_TYPE = getattr(S, hs_fieldname.const)
+        return SomeLLAbstractVariable(FIELD_TYPE)
+
+    def setfield(hs_v1, hs_fieldname, hs_value):
+        pass
+
 class __extend__(SomeLLAbstractConstant):
 
     def hint(hs_c1, hs_flags):
@@ -366,7 +374,18 @@
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractContainer)):
 
     def union((hs_cont1, hs_cont2)):
-        return SomeLLAbstractContainer(hs_cont1.contentdef.union(hs_cont2.contentdef))
+        contentdef = hs_cont1.contentdef.union(hs_cont2.contentdef)
+        return SomeLLAbstractContainer(contentdef)
+
+class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue)):
+    def union((hs_cont1, hs_val2)):
+        hs_cont1.contentdef.mark_degenerated()
+        assert hs_cont1.concretetype == hs_val2.concretetype
+        return SomeLLAbstractVariable(hs_cont1.concretetype)
+
+class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractContainer)):
+    def union((hs_val1, hs_cont2)):
+        return pair(hs_cont2, hs_val1).union()
 
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractConstant)):
 

Modified: pypy/dist/pypy/jit/test/test_hint_annotation.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_hint_annotation.py	(original)
+++ pypy/dist/pypy/jit/test/test_hint_annotation.py	Fri Mar 17 14:35:31 2006
@@ -294,6 +294,38 @@
     hs_n = ha.binding(g1.getargs()[0])
     assert hs_n.origins.keys()[0].fixed
 
+def test_prebuilt_structure():
+    S = lltype.GcStruct('S', ('n', lltype.Signed))
+    s = lltype.malloc(S)
+    def ll1(n):
+        s.n = n
+        return s.n
+    hs = hannotate(ll1, [int])
+    assert isinstance(hs, SomeLLAbstractVariable)
+
+def test_merge_substructure():
+    S = lltype.GcStruct('S', ('n', lltype.Signed))
+    T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+    def ll_function(flag):
+        t = lltype.malloc(T)
+        t.s.n = 3
+        s = lltype.malloc(S)
+        s.n = 4
+        if flag:
+            s = t.s
+        return s, t
+    hs = hannotate(ll_function, [bool])
+    assert isinstance(hs, SomeLLAbstractContainer)
+    assert not hs.contentdef.degenerated
+    assert len(hs.contentdef.fields) == 2
+    hs0 = hs.contentdef.fields['item0'].s_value       # 's'
+    assert isinstance(hs0, SomeLLAbstractContainer)
+    assert hs0.contentdef.degenerated
+    hs1 = hs.contentdef.fields['item1'].s_value       # 't'
+    assert isinstance(hs1, SomeLLAbstractContainer)
+    assert hs1.contentdef.degenerated
+
 def test_simple_fixed_call():
     def ll_help(cond, x, y):
         if cond:



More information about the Pypy-commit mailing list