[pypy-svn] r22782 - in pypy/dist/pypy/rpython/memory: . test

mwh at codespeak.net mwh at codespeak.net
Sat Jan 28 14:08:13 CET 2006


Author: mwh
Date: Sat Jan 28 14:08:11 2006
New Revision: 22782

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
Log:
(cfbolz,mwh)
Test that we handle variables without concretetypes correctly.
When looking at the graph, we realised that we need to handle return values
of type PyObject differently -- they never need to be push_alived as we are always
given a new reference to a PyObject.  So we fixed that and tested for it too.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat Jan 28 14:08:11 2006
@@ -24,8 +24,23 @@
 EXCEPTION_RAISING_OPS = ['direct_call', 'indirect_call']
 
 def var_needsgc(var):
-    vartype = var.concretetype
-    return isinstance(vartype, lltype.Ptr) and vartype._needsgc()
+    if hasattr(var, 'concretetype'):
+        vartype = var.concretetype
+        return isinstance(vartype, lltype.Ptr) and vartype._needsgc()
+    else:
+        # assume PyObjPtr
+        return True
+
+def var_ispyobj(var):
+    if hasattr(var, 'concretetype'):
+        if isinstance(var.concretetype, lltype.Ptr):
+            return var.concretetype.TO is lltype.PyObject
+        else:
+            return False
+    else:
+        # assume PyObjPtr
+        return True
+    
 
 class GCTransformer:
     def __init__(self):
@@ -73,7 +88,7 @@
                     cleanup_on_exception.extend(self.pop_alive(var))
                 op.cleanup = cleanup_on_exception
             if var_needsgc(op.result):
-                if op.opname not in ('direct_call', 'indirect_call'):
+                if op.opname not in ('direct_call', 'indirect_call') and not var_ispyobj(op.result):
                     newops.extend(self.push_alive(op.result))
                 livevars.append(op.result)
         if len(block.exits) == 0:
@@ -102,7 +117,7 @@
             return [op]
 
     def push_alive(self, var):
-        if var.concretetype.TO is lltype.PyObject:
+        if var_ispyobj(var):
             return self.push_alive_pyobj(var)
         else:
             return self.push_alive_nopyobj(var)
@@ -118,7 +133,7 @@
         return [SpaceOperation("gc_push_alive_pyobj", [var], result)]
 
     def pop_alive(self, var):
-        if var.concretetype.TO is lltype.PyObject:
+        if var_ispyobj(var):
             return self.pop_alive_pyobj(var)
         else:
             return self.pop_alive_nopyobj(var)

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Sat Jan 28 14:08:11 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.memory import gctransform
-from pypy.rpython.memory.gctransform import var_needsgc
+from pypy.rpython.memory.gctransform import var_needsgc, var_ispyobj
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem import lltype
 from pypy.objspace.flow.model import Variable
@@ -14,7 +14,10 @@
     else:
         refs_in = len([v for v in block.inputargs if var_needsgc(v)])
     push_alives = len([op for op in block.operations
-                       if op.opname.startswith('gc_push_alive')])
+                       if op.opname.startswith('gc_push_alive')]) + \
+                  len([op for op in block.operations
+                       if var_ispyobj(op.result) and 'direct_call' not in op.opname])
+    
     pop_alives = len([op for op in block.operations
                       if op.opname.startswith('gc_pop_alive')])
     calls = len([op for op in block.operations
@@ -28,10 +31,11 @@
         assert refs_in + push_alives + calls == pop_alives + refs_out
     
 
-def rtype_and_transform(func, inputtypes, transformcls):
+def rtype_and_transform(func, inputtypes, transformcls, specialize=True):
     t = TranslationContext()
     t.buildannotator().build_types(func, inputtypes)
-    t.buildrtyper().specialize(t)
+    if specialize:
+        t.buildrtyper().specialize(t)
     transformer = transformcls()
     transformer.transform(t.graphs)
     t.checkgraphs()
@@ -173,5 +177,18 @@
         f(s)
         return s.x
     t = rtype_and_transform(g, [], gctransform.GCTransformer)
-    ggraph = graphof(t, g)
         
+def test_noconcretetype():
+    def f():
+        return [1][0]
+    t = rtype_and_transform(f, [], gctransform.GCTransformer, specialize=False)
+    fgraph = graphof(t, f)
+    push_count = 0
+    pop_count = 0
+    for op in fgraph.startblock.operations:
+        if op.opname == 'gc_push_alive_pyobj':
+            push_count += 1
+        elif op.opname == 'gc_pop_alive_pyobj':
+            pop_count += 1
+    assert push_count == 0 and pop_count == 1
+    



More information about the Pypy-commit mailing list