[pypy-svn] r49815 - in pypy/branch/lazy-write-barrier/pypy: annotation doc interpreter jit/hintannotator jit/hintannotator/test lib module/__builtin__ module/__builtin__/test module/_random module/crypt objspace/std rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/ootypesystem rpython/ootypesystem/test translator/c translator/c/test translator/cli translator/goal

fijal at codespeak.net fijal at codespeak.net
Sat Dec 15 13:57:31 CET 2007


Author: fijal
Date: Sat Dec 15 13:57:29 2007
New Revision: 49815

Added:
   pypy/branch/lazy-write-barrier/pypy/module/__builtin__/interp_classobj.py
      - copied unchanged from r49814, pypy/dist/pypy/module/__builtin__/interp_classobj.py
   pypy/branch/lazy-write-barrier/pypy/module/__builtin__/test/test_classobj.py
      - copied unchanged from r49814, pypy/dist/pypy/module/__builtin__/test/test_classobj.py
Removed:
   pypy/branch/lazy-write-barrier/pypy/lib/_classobj.py
   pypy/branch/lazy-write-barrier/pypy/module/__builtin__/app_sets.py
Modified:
   pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py
   pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt
   pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py
   pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py
   pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py
   pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py
   pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py
   pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py
   pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py
   pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py
   pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py
   pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py
   pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py
   pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py
   pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py
   pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py
   pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py
   pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py
   pypy/branch/lazy-write-barrier/pypy/translator/c/database.py
   pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py
   pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py
   pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py
Log:
Merge dist -> branch


Modified: pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/annotation/builtin.py	Sat Dec 15 13:57:29 2007
@@ -16,6 +16,7 @@
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation import description
 from pypy.objspace.flow.model import Constant
+from pypy.tool.error import AnnotatorError
 import pypy.rlib.rarithmetic
 import pypy.rlib.objectmodel
 
@@ -547,6 +548,20 @@
     assert isinstance(i, SomeOOInstance)
     return SomeInteger()
 
+def ooupcast(I, i):
+    assert isinstance(I.const, ootype.Instance)
+    if ootype.isSubclass(i.ootype, I.const):
+        return SomeOOInstance(I.const)
+    else:
+        raise AnnotatorError, 'Cannot cast %s to %s' % (i.ootype, I.const)
+
+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)
+
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
 BUILTIN_ANALYZERS[ootype.new] = new
 BUILTIN_ANALYZERS[ootype.null] = null
@@ -554,6 +569,8 @@
 BUILTIN_ANALYZERS[ootype.classof] = classof
 BUILTIN_ANALYZERS[ootype.subclassof] = subclassof
 BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
+BUILTIN_ANALYZERS[ootype.ooupcast] = ooupcast
+BUILTIN_ANALYZERS[ootype.oodowncast] = oodowncast
 
 #________________________________
 # weakrefs

Modified: pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt	(original)
+++ pypy/branch/lazy-write-barrier/pypy/doc/prolog-interpreter.txt	Sat Dec 15 13:57:29 2007
@@ -25,7 +25,7 @@
 .. _`Learn Prolog Now!`: http://www.coli.uni-saarland.de/~kris/learn-prolog-now/
 .. _`A Prolog interpreter in Python`: http://codespeak.net/pypy/extradoc/paper/prolog-in-python.pdf
 
-Example useage
+Example usage
 ==============
 
 First some simple examples that show simple unification::

Modified: pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/interpreter/gateway.py	Sat Dec 15 13:57:29 2007
@@ -328,7 +328,7 @@
 
     def visit__object(self, typ):
         if typ not in (int, str, float, unicode, r_longlong):
-            assert False, "unsupported basic type in uwnrap_spec"
+            assert False, "unsupported basic type in unwrap_spec"
         self.unwrap.append("space.%s_w(%s)" % (typ.__name__,
                                                self.nextarg()))
 

Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/annotator.py	Sat Dec 15 13:57:29 2007
@@ -6,7 +6,8 @@
 from pypy.jit.hintannotator.bookkeeper import HintBookkeeper
 from pypy.jit.hintannotator.policy import HintAnnotatorPolicy
 from pypy.rpython.lltypesystem import lltype
-
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.simplify import get_funcobj
 
 class HintAnnotator(RPythonAnnotator):
 
@@ -28,6 +29,15 @@
     def getuserclassdefinitions(self):
         return []
 
+    def consider_op_new(self, hs_TYPE):
+        TYPE = hs_TYPE.const
+        if self.policy.novirtualcontainer:
+            return hintmodel.SomeLLAbstractVariable(TYPE)
+        else:
+            # XXX: ootype
+            vstructdef = self.bookkeeper.getvirtualcontainerdef(TYPE)
+            return hintmodel.SomeLLAbstractContainer(vstructdef)        
+
     def consider_op_malloc(self, hs_TYPE, hs_flags):
         TYPE = hs_TYPE.const
         flags = hs_flags.const
@@ -65,10 +75,15 @@
 
     def consider_op_ts_metacall(self, hs_f1, hs_metadesccls, *args_hs):
         bookkeeper = self.bookkeeper
-        fnobj = hs_f1.const._obj
+        fnobj = get_funcobj(hs_f1.const)
         return hintmodel.cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
                                             lltype.typeOf(fnobj).RESULT)
 
+    def consider_op_oosend(self, hs_name, *args_hs):
+        assert hs_name.concretetype is ootype.Void
+        hs_obj, args_hs = args_hs[0], args_hs[1:]
+        return hs_obj.oosend(hs_name, *args_hs)
+    
     def simplify(self):
         RPythonAnnotator.simplify(self, extra_passes=[])
 

Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/model.py	Sat Dec 15 13:57:29 2007
@@ -2,6 +2,8 @@
 from pypy.tool.pairtype import pair, pairtype
 from pypy.jit.hintannotator.bookkeeper import getbookkeeper
 from pypy.rpython.lltypesystem import lltype, lloperation
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.simplify import get_funcobj
 
 UNARY_OPERATIONS = """same_as hint getfield setfield getsubstruct getarraysize
                       getinteriorfield getinteriorarraysize setinteriorfield
@@ -20,6 +22,14 @@
                       ptr_nonzero
                       ptr_iszero
                       is_early_constant
+                      oogetfield
+                      oosetfield
+                      oononnull
+                      ooupcast
+                      oodowncast
+                      oois
+                      subclassof
+                      instanceof
                       """.split()
 
 BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift
@@ -244,7 +254,11 @@
 
     def __init__(self, contentdef):
         self.contentdef = contentdef
-        self.concretetype = lltype.Ptr(contentdef.T)
+        T = contentdef.T
+        if isinstance(T, ootype.OOType):
+            self.concretetype = T
+        else:
+            self.concretetype = lltype.Ptr(T)
 
     def annotationcolor(self):
         """Compute the color of the variables with this annotation
@@ -339,9 +353,16 @@
         FIELD_TYPE = getattr(S, hs_fieldname.const)
         return variableoftype(FIELD_TYPE, hs_v1.deepfrozen)
 
+    def oogetfield(hs_v1, hs_fieldname):
+        _, FIELD_TYPE = hs_v1.concretetype._lookup_field(hs_fieldname.const)
+        return variableoftype(FIELD_TYPE, hs_v1.deepfrozen)
+
     def setfield(hs_v1, hs_fieldname, hs_value):
         pass
 
+    def oosetfield(hs_v1, hs_fieldname, hs_value):
+        pass
+
     def getsubstruct(hs_v1, hs_fieldname):
         S = hs_v1.concretetype.TO
         FIELD_TYPE = getattr(S, hs_fieldname.const)
@@ -406,6 +427,9 @@
         # function
         return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
 
+    def oosend(hs_v1, hs_name, *args_hs): 
+        RESTYPE = getbookkeeper().current_op_concretetype()
+        return SomeLLAbstractVariable(RESTYPE)
 
 class __extend__(SomeLLAbstractConstant):
 
@@ -428,7 +452,7 @@
 
     def direct_call(hs_f1, *args_hs):
         bookkeeper = getbookkeeper()
-        fnobj = hs_f1.const._obj
+        fnobj = get_funcobj(hs_f1.const)
         if (bookkeeper.annotator.policy.oopspec and
             hasattr(fnobj._callable, 'oopspec')):
             # try to handle the call as a high-level operation
@@ -473,9 +497,34 @@
         # function
         return annmodel.unionof(hs_res, bookkeeper.current_op_binding())
 
+    def oosend(hs_c1, hs_name, *args_hs): 
+        TYPE = hs_c1.concretetype
+        name = hs_name.const
+        graph_list = TYPE._lookup_graphs(name)
+        if not graph_list:
+            # it's a method of a BuiltinType
+            bk = getbookkeeper()
+            origin = bk.myorigin()
+            d = setadd(hs_c1.origins, origin)
+            RESTYPE = bk.current_op_concretetype() 
+            hs_res = SomeLLAbstractConstant(RESTYPE, d,
+                                            eager_concrete = hs_c1.eager_concrete,
+                                            myorigin = origin)
+            # if hs_c1.is_constant(): ...
+            return hs_res
+        #import pdb;pdb.set_trace()
+
     def getfield(hs_c1, hs_fieldname):
         S = hs_c1.concretetype.TO
         FIELD_TYPE = getattr(S, hs_fieldname.const)
+        return hs_c1.getfield_impl(S, FIELD_TYPE)
+
+    def oogetfield(hs_c1, hs_fieldname):
+        S = hs_c1.concretetype
+        _, FIELD_TYPE = S._lookup_field(hs_fieldname.const)
+        return hs_c1.getfield_impl(S, FIELD_TYPE)
+
+    def getfield_impl(hs_c1, S, FIELD_TYPE):
         if S._hints.get('immutable', False) or hs_c1.deepfrozen:
             origin = getbookkeeper().myorigin()
             d = setadd(hs_c1.origins, origin)

Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_annotator.py	Sat Dec 15 13:57:29 2007
@@ -20,956 +20,1002 @@
 P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True,
                                   entrypoint_returns_red=False)
 
-def hannotate(func, argtypes, policy=P_DEFAULT, annotator=False, inline=None,
-              backendoptimize=False):
-    # build the normal ll graphs for ll_function
-    t = TranslationContext()
-    a = t.buildannotator()
-    a.build_types(func, argtypes)
-    rtyper = t.buildrtyper()
-    rtyper.specialize()
-    if inline:
-        auto_inlining(t, threshold=inline)
-    if backendoptimize:
-        from pypy.translator.backendopt.all import backend_optimizations
-        backend_optimizations(t)
-    graph1 = graphof(t, func)
-
-    # build hint annotator types
-    hannotator = HintAnnotator(base_translator=t, policy=policy)
-    hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
-                                                                {OriginFlags(): True})
-                                         for v in graph1.getargs()])
-    hannotator.simplify()
-    t = hannotator.translator
-    if conftest.option.view:
-        t.view()
-    if annotator:
-        return hs, hannotator
-    else:
-        return hs
-
-def test_simple():
-    def ll_function(x, y):
-        return x + y
-    hs = hannotate(ll_function, [int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert len(hs.origins) == 3
-    assert hs.concretetype == lltype.Signed
-
-def test_join():
-    def ll_function(cond, x,y):
-        if cond:
-            z = x+y
-        else:
-            z = x-y
-        return z
-    hs = hannotate(ll_function, [bool, int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert len(hs.origins) == 4
-    assert hs.concretetype == lltype.Signed
+class AbstractAnnotatorTest:
+    type_system = None
+    
+    def hannotate(self, func, argtypes, policy=P_DEFAULT, annotator=False, inline=None,
+                  backendoptimize=False):
+        # build the normal ll graphs for ll_function
+        t = TranslationContext()
+        a = t.buildannotator()
+        a.build_types(func, argtypes)
+        rtyper = t.buildrtyper(type_system = self.type_system)
+        rtyper.specialize()
+        if inline:
+            auto_inlining(t, threshold=inline)
+        if backendoptimize:
+            from pypy.translator.backendopt.all import backend_optimizations
+            backend_optimizations(t)
+        graph1 = graphof(t, func)
+
+        # build hint annotator types
+        hannotator = HintAnnotator(base_translator=t, policy=policy)
+        hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
+                                                                    {OriginFlags(): True})
+                                             for v in graph1.getargs()])
+        hannotator.simplify()
+        t = hannotator.translator
+        if conftest.option.view:
+            t.view()
+        if annotator:
+            return hs, hannotator
+        else:
+            return hs
+
+
+class BaseAnnotatorTest(AbstractAnnotatorTest):
+    
+    def test_simple(self):
+        def ll_function(x, y):
+            return x + y
+        hs = self.hannotate(ll_function, [int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert len(hs.origins) == 3
+        assert hs.concretetype == lltype.Signed
+
+    def test_join(self):
+        def ll_function(cond, x,y):
+            if cond:
+                z = x+y
+            else:
+                z = x-y
+            return z
+        hs = self.hannotate(ll_function, [bool, int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert len(hs.origins) == 4
+        assert hs.concretetype == lltype.Signed
 
 
-def test_simple_hint_result():
-    def ll_function(cond, x,y):
-        if cond:
-            z = x+y
-        else:
-            z = x-y
-        z = hint(z, concrete=True)
-        return z
-    hs = hannotate(ll_function, [bool, int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.eager_concrete
-    assert hs.concretetype == lltype.Signed
+    def test_simple_hint_result(self):
+        def ll_function(cond, x,y):
+            if cond:
+                z = x+y
+            else:
+                z = x-y
+            z = hint(z, concrete=True)
+            return z
+        hs = self.hannotate(ll_function, [bool, int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.eager_concrete
+        assert hs.concretetype == lltype.Signed
+
+    def test_deepfreeze(self):
+
+        A = lltype.GcArray(lltype.Signed)
+
+        def ll_function(a, i):
+            a = hint(a, deepfreeze=True)
+            res = a[i]
+            res = hint(res, concrete=True)
+
+            res = hint(res, variable=True)
+            return res
+
+        hs = self.hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(A)), int])
+        assert type(hs) is SomeLLAbstractVariable
+        assert hs.concretetype == lltype.Signed
+
+    def test_lists_deepfreeze(self):
+
+        l1 = [1,2,3,4,5]
+        l2 = [6,7,8,9,10]
+
+        def getlist(n):
+            if n:
+                return l1
+            else:
+                return l2
 
-def test_deepfreeze():
+        def ll_function(n, i):
+            l = getlist(n)
+            l = hint(l, deepfreeze=True)
 
-    A = lltype.GcArray(lltype.Signed)
-    
-    def ll_function(a, i):
-        a = hint(a, deepfreeze=True)
-        res = a[i]
-        res = hint(res, concrete=True)
-        
-        res = hint(res, variable=True)
-        return res
-
-    hs = hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(A)), int])
-    assert type(hs) is SomeLLAbstractVariable
-    assert hs.concretetype == lltype.Signed
+            res = l[i]
+            res = hint(res, concrete=True)
 
-def test_lists_deepfreeze():
+            res = hint(res, variable=True)
+            return res
 
-    l1 = [1,2,3,4,5]
-    l2 = [6,7,8,9,10]
-    
-    def getlist(n):
-        if n:
-            return l1
-        else:
-            return l2
-    
-    def ll_function(n, i):
-        l = getlist(n)
-        l = hint(l, deepfreeze=True)
-
-        res = l[i]
-        res = hint(res, concrete=True)
-        
-        res = hint(res, variable=True)
-        return res
+        hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+        assert hs.concretetype == lltype.Signed
 
-    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
-    assert hs.concretetype == lltype.Signed
+    def test_dicts_deepfreeze(self):
 
-def test_dicts_deepfreeze():
+        d1 = {1:2, 2:3}
+        d2 = {2:3, 3:4}
 
-    d1 = {1:2, 2:3}
-    d2 = {2:3, 3:4}
-    
-    def getdict(n):
-        if n:
-            return d1
-        else:
-            return d2
-    
-    def ll_function(n, i):
-        d = getdict(n)
-        d = hint(d, deepfreeze=True)
-
-        res = d[i]
-        res = hint(res, concrete=True)
-        
-        res = hint(res, variable=True)
-        return res
-
-    # must backendoptimize to remove the mallocs related to the interior ptrs
-    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL,
-                   backendoptimize=True)
-    assert hs.concretetype == lltype.Signed
-
-
-def test_simple_hint_origins():
-    def ll_function(cond, x,y):
-        if cond:
-            z = x+y
-        else:
-            z = x-y
-        z1 = hint(z, concrete=True)
-        return z # origin of z1
-    hs, ha = hannotate(ll_function, [bool, int, int], annotator=True)
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert len(hs.origins) == 4
-    assert hs.is_fixed()
-    assert hs.concretetype == lltype.Signed
-    ll_function_graph = graphof(ha.base_translator, ll_function)
-    gdesc = ha.bookkeeper.getdesc(ll_function_graph)
-    _, x_v, y_v = gdesc._cache[None].getargs()
-    assert ha.binding(x_v).is_fixed()
-    assert ha.binding(y_v).is_fixed()
-    
-def test_simple_variable():
-    def ll_function(x,y):
-        x = hint(x, variable=True) # special hint only for testing purposes!!!
-        return x + y
-    hs = hannotate(ll_function, [int, int])
-    assert type(hs) is SomeLLAbstractVariable
-    assert hs.concretetype == lltype.Signed
-    
-def test_simple_concrete_propagation():
-    def ll_function(x,y):
-        x = hint(x, concrete=True)
-        return x + y
-    hs = hannotate(ll_function, [int, int])
-    assert type(hs) is SomeLLAbstractConstant
-    assert hs.eager_concrete
-    assert hs.concretetype == lltype.Signed
-
-def test_union():
-    unionof = annmodel.unionof
-    av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
-    cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True), SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True)
-    ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
-    ac3 = SomeLLAbstractConstant(lltype.Signed, {})
-    ac3.const = 3
-    ac4 = SomeLLAbstractConstant(lltype.Signed, {})
-    ac4.const = 4
-    assert unionof(av1, av2) == av1
-    assert unionof(cv1, cv2) == cv2
-    assert unionof(ac1, ac2) == ac1
-    assert unionof(ac3, ac3) == ac3
-    assert unionof(ac3, ac2) == ac1
-    assert unionof(ac4, ac3) == ac1
-    # degenerating cases
-    py.test.raises(annmodel.UnionError, "unionof(cv1, av1)")
-    py.test.raises(annmodel.UnionError, "unionof(av1, cv1)")
-
-    # MAYBE...
-    #py.test.raises(annmodel.UnionError, "unionof(ac1, cv1)")
-    #py.test.raises(annmodel.UnionError, "unionof(cv1, ac1)")
-    assert unionof(cv1, ac1) == ac1
-    assert unionof(ac1, cv1) == ac1
-    
-    # constant with values
-    assert unionof(av1, ac1) == av1
-    assert unionof(ac1, av1) == av1
-    assert unionof(ac3, av1) == av1
-    assert unionof(av2, ac4) == av1
-
-def test_op_meet():
-    def meet(hs1, hs2):
-        bk = HintBookkeeper(None)
-        block = flowmodel.Block([])
-        block.operations.append(flowmodel.SpaceOperation('x', [],
-                                                         flowmodel.Variable()))
-        bk.enter(("graph", block, 0))
-        bk.current_op_concretetype = lambda: lltype.Signed     # hack
-        return pair(hs1, hs2).int_add()
-    av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
-    cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, True), SomeLLAbstractConstant(lltype.Signed, {}, True)
-    ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
-    assert meet(av1, av2) == av1
-    res = meet(cv1, cv2)
-    assert res.eager_concrete
-    assert isinstance(meet(ac1, ac2), SomeLLAbstractConstant)
-    assert meet(ac1, cv1).eager_concrete
-    assert meet(cv1, ac1).eager_concrete
-    assert meet(av1, cv1) == av1
-    assert meet(cv1, av1) == av1
-    assert meet(ac1, av1) == av1
-    assert meet(av1, ac1) == av1
-
-def test_loop():
-    def ll_function(x, y):
-        while x > 0:
-            y += x
-            x -= 1
-        return y
-    hs = hannotate(ll_function, [int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 4
-
-def test_loop1():
-    def ll_function(x, y):
-        while x > 0:
-            x1 = hint(x, concrete=True)
-            if x1 == 7:
+        def getdict(n):
+            if n:
+                return d1
+            else:
+                return d2
+
+        def ll_function(n, i):
+            d = getdict(n)
+            d = hint(d, deepfreeze=True)
+
+            res = d[i]
+            res = hint(res, concrete=True)
+
+            res = hint(res, variable=True)
+            return res
+
+        # must backendoptimize to remove the mallocs related to the interior ptrs
+        hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL,
+                       backendoptimize=True)
+        assert hs.concretetype == lltype.Signed
+
+
+    def test_simple_hint_origins(self):
+        def ll_function(cond, x,y):
+            if cond:
+                z = x+y
+            else:
+                z = x-y
+            z1 = hint(z, concrete=True)
+            return z # origin of z1
+        hs, ha = self.hannotate(ll_function, [bool, int, int], annotator=True)
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert len(hs.origins) == 4
+        assert hs.is_fixed()
+        assert hs.concretetype == lltype.Signed
+        ll_function_graph = graphof(ha.base_translator, ll_function)
+        gdesc = ha.bookkeeper.getdesc(ll_function_graph)
+        _, x_v, y_v = gdesc._cache[None].getargs()
+        assert ha.binding(x_v).is_fixed()
+        assert ha.binding(y_v).is_fixed()
+
+    def test_simple_variable(self):
+        def ll_function(x,y):
+            x = hint(x, variable=True) # special hint only for testing purposes!!!
+            return x + y
+        hs = self.hannotate(ll_function, [int, int])
+        assert type(hs) is SomeLLAbstractVariable
+        assert hs.concretetype == lltype.Signed
+
+    def test_simple_concrete_propagation(self):
+        def ll_function(x,y):
+            x = hint(x, concrete=True)
+            return x + y
+        hs = self.hannotate(ll_function, [int, int])
+        assert type(hs) is SomeLLAbstractConstant
+        assert hs.eager_concrete
+        assert hs.concretetype == lltype.Signed
+
+    def test_union(self):
+        unionof = annmodel.unionof
+        av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
+        cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True), SomeLLAbstractConstant(lltype.Signed, {}, eager_concrete=True)
+        ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
+        ac3 = SomeLLAbstractConstant(lltype.Signed, {})
+        ac3.const = 3
+        ac4 = SomeLLAbstractConstant(lltype.Signed, {})
+        ac4.const = 4
+        assert unionof(av1, av2) == av1
+        assert unionof(cv1, cv2) == cv2
+        assert unionof(ac1, ac2) == ac1
+        assert unionof(ac3, ac3) == ac3
+        assert unionof(ac3, ac2) == ac1
+        assert unionof(ac4, ac3) == ac1
+        # degenerating cases
+        py.test.raises(annmodel.UnionError, "unionof(cv1, av1)")
+        py.test.raises(annmodel.UnionError, "unionof(av1, cv1)")
+
+        # MAYBE...
+        #py.test.raises(annmodel.UnionError, "unionof(ac1, cv1)")
+        #py.test.raises(annmodel.UnionError, "unionof(cv1, ac1)")
+        assert unionof(cv1, ac1) == ac1
+        assert unionof(ac1, cv1) == ac1
+
+        # constant with values
+        assert unionof(av1, ac1) == av1
+        assert unionof(ac1, av1) == av1
+        assert unionof(ac3, av1) == av1
+        assert unionof(av2, ac4) == av1
+
+    def test_op_meet(self):
+        def meet(hs1, hs2):
+            bk = HintBookkeeper(None)
+            block = flowmodel.Block([])
+            block.operations.append(flowmodel.SpaceOperation('x', [],
+                                                             flowmodel.Variable()))
+            bk.enter(("graph", block, 0))
+            bk.current_op_concretetype = lambda: lltype.Signed     # hack
+            return pair(hs1, hs2).int_add()
+        av1, av2 = SomeLLAbstractVariable(lltype.Signed), SomeLLAbstractVariable(lltype.Signed)
+        cv1, cv2 = SomeLLAbstractConstant(lltype.Signed, {}, True), SomeLLAbstractConstant(lltype.Signed, {}, True)
+        ac1, ac2 = SomeLLAbstractConstant(lltype.Signed, {}), SomeLLAbstractConstant(lltype.Signed, {})
+        assert meet(av1, av2) == av1
+        res = meet(cv1, cv2)
+        assert res.eager_concrete
+        assert isinstance(meet(ac1, ac2), SomeLLAbstractConstant)
+        assert meet(ac1, cv1).eager_concrete
+        assert meet(cv1, ac1).eager_concrete
+        assert meet(av1, cv1) == av1
+        assert meet(cv1, av1) == av1
+        assert meet(ac1, av1) == av1
+        assert meet(av1, ac1) == av1
+
+    def test_loop(self):
+        def ll_function(x, y):
+            while x > 0:
                 y += x
-            x -= 1
-        return y
-    hs = hannotate(ll_function, [int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 4
-
-def test_simple_struct():
-    S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
-                                      ('world', lltype.Signed),
-                        hints={'immutable': True})
-    def ll_function(s):
-        return s.hello * s.world
-    hs = hannotate(ll_function, [annmodel.SomePtr(lltype.Ptr(S))])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 4
-
-def test_simple_struct_malloc():
-    S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
-                                      ('world', lltype.Signed))               
-    def ll_function(x):
-        s = lltype.malloc(S)
-        s.hello = x
-        return s.hello + s.world
-
-    hs = hannotate(ll_function, [int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 2
-
-def test_container_union():
-    S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
-                                      ('world', lltype.Signed))               
-    def ll_function(cond, x, y):
-        if cond:
-            s = lltype.malloc(S)
+                x -= 1
+            return y
+        hs = self.hannotate(ll_function, [int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 4
+
+    def test_loop1(self):
+        def ll_function(x, y):
+            while x > 0:
+                x1 = hint(x, concrete=True)
+                if x1 == 7:
+                    y += x
+                x -= 1
+            return y
+        hs = self.hannotate(ll_function, [int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 4
+
+    def test_simple_struct(self):
+        S = self.make_struct('helloworld', ('hello', lltype.Signed),
+                                           ('world', lltype.Signed),
+                             hints={'immutable': True})
+        def ll_function(s):
+            return s.hello * s.world
+        hs = self.hannotate(ll_function, [self.annotate_struct(S)])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 4
+
+    def test_simple_struct_malloc(self):
+        S = self.make_struct('helloworld', ('hello', lltype.Signed),
+                                           ('world', lltype.Signed))
+        malloc = self.malloc
+        def ll_function(x):
+            s = malloc(S)
             s.hello = x
-        else:
-            s = lltype.malloc(S)
-            s.world = y
-        return s.hello + s.world
+            return s.hello + s.world
 
-    hs = hannotate(ll_function, [bool, int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 3
-
-def test_simple_call():
-    def ll2(x, y, z):
-        return x + (y + 42)
-    def ll1(x, y, z):
-        return ll2(x, y - z, x + y + z)
-    hs = hannotate(ll1, [int, int, int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 5
-
-def test_simple_list_operations():
-    def ll_function(x, y, index):
-        l = [x]
-        l.append(y)
-        return l[index]
-    hs = hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 4
-
-def test_some_more_list_operations():
-    def ll_function(x, y, index):
-        l = []
-        l.append(x)
-        l[0] = y
-        return (l+list(l))[index]
-    hs = hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-    assert len(hs.origins) == 4
-
-def test_make_a_list():
-    def ll_function(x, y):
-        return [x, y]
-    hs = hannotate(ll_function, [int, int], policy=P_OOPSPEC)
-    assert isinstance(hs, SomeLLAbstractContainer)
-
-def test_frozen_list():
-    lst = [5, 7, 9]
-    def ll_function(x):
-        mylist = hint(lst, deepfreeze=True)
-        z = mylist[x]
-        hint(z, concrete=True)
-        return z
-    hs = hannotate(ll_function, [int], policy=P_OOPSPEC_NOVIRTUAL)
-    assert hs.is_green()
-
-def test_simple_cast_pointer():
-    GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
-    GCS2 = lltype.GcStruct('s2', ('sub', GCS1), ('y', lltype.Signed))
-    PGCS1 = lltype.Ptr(GCS1)
-    PGCS2 = lltype.Ptr(GCS2)
-    def ll1():
-        s2 = lltype.malloc(GCS2)
-        return lltype.cast_pointer(PGCS1, s2)
-    hs = hannotate(ll1, [])
-    assert isinstance(hs, SomeLLAbstractContainer)
-    assert hs.concretetype == PGCS1
-    def ll1():
-        s2 = lltype.malloc(GCS2)
-        s1 = s2.sub
-        return lltype.cast_pointer(PGCS2, s1)
-    hs = hannotate(ll1, [])
-    assert isinstance(hs, SomeLLAbstractContainer)
-    assert hs.concretetype == PGCS2
-
-def test_getarrayitem():
-    A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
-    a = lltype.malloc(A, 10)
-    def ll1(n):
-        v = a[n]
-        v = hint(v, concrete=True)
-        return v
-    hs, ha = hannotate(ll1, [int], annotator=True)
-    assert hs.eager_concrete
-    g1 = graphof(ha.translator, ll1)
-    hs_n = ha.binding(g1.getargs()[0])
-    assert hs_n.origins.keys()[0].fixed
-
-def test_getvarrayitem():
-    A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
-    def ll1(n):
-        a = lltype.malloc(A, 10)
-        v = a[n]
-        v = hint(v, concrete=True)
-        return v
-    hs, ha = hannotate(ll1, [int], annotator=True)
-    assert hs.eager_concrete
-    g1 = graphof(ha.translator, ll1)
-    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_degenerated_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_degenerated_merge_cross_substructure():
-    py.test.skip("no longer a valid test")
-    from pypy.rlib import objectmodel
-    S = lltype.Struct('S', ('n', lltype.Signed))
-    T = lltype.GcStruct('T', ('s', S), ('s1', S), ('n', lltype.Float))
-
-    def ll_function(flag):
-        t = lltype.malloc(T)
-        t.s.n = 3
-        t.s1.n = 3
-        if flag:
-            s = t.s
-        else:
-            s = t.s1
-        objectmodel.keepalive_until_here(t)
-        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:
-            z = x+y
-        else:
-            z = x-y
-        return z
-    def ll_function(cond, x,y, x1, y1):
-        z1 = ll_help(cond, x1, y1)
-        z = ll_help(cond, x, y)
-        z = hint(z, concrete=True)
-        return z
-    hs, ha  = hannotate(ll_function, [bool, int, int, int, int], annotator=True)
-    assert hs.eager_concrete
-    assert hs.concretetype == lltype.Signed
-    ll_help_graph = graphof(ha.base_translator, ll_help)
-    gdesc = ha.bookkeeper.getdesc(ll_help_graph)
-    assert not ha.binding(gdesc._cache[None].getreturnvar()).is_fixed()
-    assert len(gdesc._cache) == 2
-    assert ha.binding(gdesc._cache['fixed'].getreturnvar()).is_fixed()    
-
-def test_specialize_calls():
-    def ll_add(x, y):
-        return x+y
-    def ll_function(x,y):
-        z0 = ll_add(y, 2)
-        z1 = ll_add(x, y)
-        x1 = hint(x, concrete=True)
-        z2 = ll_add(x1, y)
-        return z2
-    hs, ha  = hannotate(ll_function, [int, int], annotator=True)
-    assert hs.eager_concrete
-    assert hs.concretetype == lltype.Signed
-    ll_add_graph = graphof(ha.base_translator, ll_add)
-    gdesc = ha.bookkeeper.getdesc(ll_add_graph)    
-    assert len(gdesc._cache) == 2
-    assert 'Exxx' in gdesc._cache
-    v1, v2 = gdesc._cache['Exxx'].getargs()
-
-    assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
-    assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
-    assert ha.binding(v1).eager_concrete
-    assert not ha.binding(v2).is_fixed()
-
-def test_specialize_deepfreeze_calls():
+        hs = self.hannotate(ll_function, [int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 2
+
+    def test_container_union(self):
+        S = self.make_struct('helloworld', ('hello', lltype.Signed),
+                                           ('world', lltype.Signed))
+        malloc = self.malloc
+        def ll_function(cond, x, y):
+            if cond:
+                s = malloc(S)
+                s.hello = x
+            else:
+                s = malloc(S)
+                s.world = y
+            return s.hello + s.world
+
+        hs = self.hannotate(ll_function, [bool, int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 3
+
+    def test_simple_call(self):
+        def ll2(x, y, z):
+            return x + (y + 42)
+        def ll1(x, y, z):
+            return ll2(x, y - z, x + y + z)
+        hs = self.hannotate(ll1, [int, int, int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 5
+
+    def test_simple_list_operations(self):
+        def ll_function(x, y, index):
+            l = [x]
+            l.append(y)
+            return l[index]
+        hs = self.hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 4
+
+    def test_some_more_list_operations(self):
+        def ll_function(x, y, index):
+            l = []
+            l.append(x)
+            l[0] = y
+            return (l+list(l))[index]
+        hs = self.hannotate(ll_function, [int, int, int], policy=P_OOPSPEC)
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+        assert len(hs.origins) == 4
+
+    def test_make_a_list(self):
+        def ll_function(x, y):
+            return [x, y]
+        hs = self.hannotate(ll_function, [int, int], policy=P_OOPSPEC)
+        assert isinstance(hs, SomeLLAbstractContainer)
+
+    def test_frozen_list(self):
+        lst = [5, 7, 9]
+        def ll_function(x):
+            mylist = hint(lst, deepfreeze=True)
+            z = mylist[x]
+            hint(z, concrete=True)
+            return z
+        hs = self.hannotate(ll_function, [int], policy=P_OOPSPEC_NOVIRTUAL)
+        assert hs.is_green()
+
+    def test_prebuilt_structure(self):
+        S = self.make_struct('S', ('n', lltype.Signed))
+        s = self.malloc(S)
+        def ll1(n):
+            s.n = n
+            return s.n
+        hs = self.hannotate(ll1, [int])
+        assert isinstance(hs, SomeLLAbstractVariable)
+
+    def test_simple_fixed_call(self):
+        def ll_help(cond, x, y):
+            if cond:
+                z = x+y
+            else:
+                z = x-y
+            return z
+        def ll_function(cond, x,y, x1, y1):
+            z1 = ll_help(cond, x1, y1)
+            z = ll_help(cond, x, y)
+            z = hint(z, concrete=True)
+            return z
+        hs, ha  = self.hannotate(ll_function, [bool, int, int, int, int], annotator=True)
+        assert hs.eager_concrete
+        assert hs.concretetype == lltype.Signed
+        ll_help_graph = graphof(ha.base_translator, ll_help)
+        gdesc = ha.bookkeeper.getdesc(ll_help_graph)
+        assert not ha.binding(gdesc._cache[None].getreturnvar()).is_fixed()
+        assert len(gdesc._cache) == 2
+        assert ha.binding(gdesc._cache['fixed'].getreturnvar()).is_fixed()    
+
+    def test_specialize_calls(self):
+        def ll_add(x, y):
+            return x+y
+        def ll_function(x,y):
+            z0 = ll_add(y, 2)
+            z1 = ll_add(x, y)
+            x1 = hint(x, concrete=True)
+            z2 = ll_add(x1, y)
+            return z2
+        hs, ha  = self.hannotate(ll_function, [int, int], annotator=True)
+        assert hs.eager_concrete
+        assert hs.concretetype == lltype.Signed
+        ll_add_graph = graphof(ha.base_translator, ll_add)
+        gdesc = ha.bookkeeper.getdesc(ll_add_graph)    
+        assert len(gdesc._cache) == 2
+        assert 'Exxx' in gdesc._cache
+        v1, v2 = gdesc._cache['Exxx'].getargs()
+
+        assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
+        assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
+        assert ha.binding(v1).eager_concrete
+        assert not ha.binding(v2).is_fixed()
+
+    def test_specialize_deepfreeze_calls(self):
+
+        l1 = [1,2,3,4,5]
+        l2 = [6,7,8,9,10]
+
+        def getlist(n):
+            if n:
+                return l1
+            else:
+                return l2
 
-    l1 = [1,2,3,4,5]
-    l2 = [6,7,8,9,10]
-    
-    def getlist(n):
-        if n:
-            return l1
-        else:
-            return l2
+        def ll_get(l, i):
+            return l[i]
 
-    def ll_get(l, i):
-        return l[i]
+        def ll_function(n, i):
+            l = getlist(n)
 
-    def ll_function(n, i):
-        l = getlist(n)
+            l2 = ll_get(l, 0)
+
+            l = hint(l, deepfreeze=True)
+            res = ll_get(l, i)
+            return res
+
+        hs, ha = self.hannotate(ll_function, [int, int], annotator=True, policy=P_NOVIRTUAL)
+        assert hs.deepfrozen
+        assert hs.concretetype == lltype.Signed
+        ll_get_graph = graphof(ha.base_translator, ll_get)
+        gdesc = ha.bookkeeper.getdesc(ll_get_graph)    
+        assert len(gdesc._cache) == 2
+        assert 'xDxx' in gdesc._cache
+        v1, v2 = gdesc._cache['xDxx'].getargs()
+
+        assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
+        assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
+        assert ha.binding(v1).deepfrozen
+
+    def test_deepfreeze_variables(self):
+        l1 = [[1], [2, 3], [4], []]
+        def ll_function(i):
+            i = hint(i, variable=True)
+            l = hint(l1, deepfreeze=True)
+            return l[i]
+
+        hs, ha = self.hannotate(ll_function, [int], annotator=True, policy=P_NOVIRTUAL)
+        assert isinstance(hs, SomeLLAbstractVariable)
+        assert hs.deepfrozen
+
+    def test_propagate_fixing_across_func_arguments(self):
+        def ll_func2(z):
+            z = hint(z, concrete=True)
+            return z + 1
+        def ll_function(cond, x,y):
+            if cond:
+                z = x+y
+            else:
+                z = x-y
+            z = ll_func2(z)
+            return z
+        hs, ha = self.hannotate(ll_function, [bool, int, int], annotator=True)
+        assert hs.eager_concrete
+        assert hs.concretetype == lltype.Signed
+        ll_function_graph = graphof(ha.base_translator, ll_function)
+        gdesc = ha.bookkeeper.getdesc(ll_function_graph)
+        _, x_v, y_v = gdesc._cache[None].getargs()
+        assert ha.binding(x_v).is_fixed()
+        assert ha.binding(y_v).is_fixed()
+
+    def test_hannotate_plus_minus(self):
+        def ll_plus_minus(s, x, y):
+            acc = x
+            n = len(s)
+            pc = 0
+            while pc < n:
+                op = s[pc]
+                op = hint(op, concrete=True)
+                if op == '+':
+                    acc += y
+                elif op == '-':
+                    acc -= y
+                pc += 1
+            return acc
+        assert ll_plus_minus("+-+", 0, 2) == 2
+        self.hannotate(ll_plus_minus, [str, int, int])
+        self.hannotate(ll_plus_minus, [str, int, int], inline=100000)
+
+    def test_invalid_hint_1(self):
+        S = self.make_struct('S', ('x', lltype.Signed))
+        def ll_getitem_switch(s):
+            n = s.x    # -> variable
+            return hint(n, concrete=True)
+        py.test.raises(HintError, self.hannotate,
+                       ll_getitem_switch, [self.annotate_struct(S)])
+
+    def undecided_relevance_test_invalid_hint_2(self):
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+        def ll_getitem_switch(s):
+            if s.x > 0:   # variable exitswitch
+                sign = 1
+            else:
+                sign = -1
+            return hint(sign, concrete=True)
+        py.test.skip("in-progress: I think we expect a HintError here, do we?")
+        py.test.raises(HintError, hannotate,
+                       ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
 
-        l2 = ll_get(l, 0)
-
-        l = hint(l, deepfreeze=True)
-        res = ll_get(l, i)
-        return res
-
-    hs, ha = hannotate(ll_function, [int, int], annotator=True, policy=P_NOVIRTUAL)
-    assert hs.deepfrozen
-    assert hs.concretetype == lltype.Signed
-    ll_get_graph = graphof(ha.base_translator, ll_get)
-    gdesc = ha.bookkeeper.getdesc(ll_get_graph)    
-    assert len(gdesc._cache) == 2
-    assert 'xDxx' in gdesc._cache
-    v1, v2 = gdesc._cache['xDxx'].getargs()
-
-    assert isinstance(ha.binding(v1), SomeLLAbstractConstant)
-    assert isinstance(ha.binding(v2), SomeLLAbstractConstant)
-    assert ha.binding(v1).deepfrozen
-
-def test_deepfreeze_variables():
-    l1 = [[1], [2, 3], [4], []]
-    def ll_function(i):
-        i = hint(i, variable=True)
-        l = hint(l1, deepfreeze=True)
-        return l[i]
-
-    hs, ha = hannotate(ll_function, [int], annotator=True, policy=P_NOVIRTUAL)
-    assert isinstance(hs, SomeLLAbstractVariable)
-    assert hs.deepfrozen
-
-def test_propagate_fixing_across_func_arguments():
-    def ll_func2(z):
-        z = hint(z, concrete=True)
-        return z + 1
-    def ll_function(cond, x,y):
-        if cond:
-            z = x+y
-        else:
-            z = x-y
-        z = ll_func2(z)
-        return z
-    hs, ha = hannotate(ll_function, [bool, int, int], annotator=True)
-    assert hs.eager_concrete
-    assert hs.concretetype == lltype.Signed
-    ll_function_graph = graphof(ha.base_translator, ll_function)
-    gdesc = ha.bookkeeper.getdesc(ll_function_graph)
-    _, x_v, y_v = gdesc._cache[None].getargs()
-    assert ha.binding(x_v).is_fixed()
-    assert ha.binding(y_v).is_fixed()
-
-def test_hannotate_plus_minus():
-    def ll_plus_minus(s, x, y):
-        acc = x
-        n = len(s)
-        pc = 0
-        while pc < n:
-            op = s[pc]
-            op = hint(op, concrete=True)
-            if op == '+':
-                acc += y
-            elif op == '-':
-                acc -= y
-            pc += 1
-        return acc
-    assert ll_plus_minus("+-+", 0, 2) == 2
-    hannotate(ll_plus_minus, [str, int, int])
-    hannotate(ll_plus_minus, [str, int, int], inline=100000)
-
-def test_invalid_hint_1():
-    S = lltype.GcStruct('S', ('x', lltype.Signed))
-    def ll_getitem_switch(s):
-        n = s.x    # -> variable
-        return hint(n, concrete=True)
-    py.test.raises(HintError, hannotate,
-                   ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
-
-def undecided_relevance_test_invalid_hint_2():
-    S = lltype.GcStruct('S', ('x', lltype.Signed))
-    def ll_getitem_switch(s):
-        if s.x > 0:   # variable exitswitch
-            sign = 1
-        else:
-            sign = -1
-        return hint(sign, concrete=True)
-    py.test.skip("in-progress: I think we expect a HintError here, do we?")
-    py.test.raises(HintError, hannotate,
-                   ll_getitem_switch, [annmodel.SomePtr(lltype.Ptr(S))])
-
-
-def test_raise_exc():
-    class E(Exception):
-        pass
-    def f1():
-        raise E
-    hannotate(f1, [], policy=P_OOPSPEC_NOVIRTUAL)
-
-    def f2():
-        e = E()
-        e.a = 3
-        raise e
-    hannotate(f2, [], policy=P_OOPSPEC_NOVIRTUAL)    
-    
 
-def test_raise_and_catch_exc():
-    class E(Exception):
-        pass
-    def f(flag):
-        if flag:
+    def test_raise_exc(self):
+        class E(Exception):
+            pass
+        def f1():
             raise E
+        self.hannotate(f1, [], policy=P_OOPSPEC_NOVIRTUAL)
 
-    def g(flag):
-        try:
-            f(flag)
-        except E:
-            return -1
-        return 0
-            
-    hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed
-
-    def f(flag):
-        if flag:
+        def f2():
             e = E()
             e.a = 3
             raise e
-        
-    hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)    
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.concretetype == lltype.Signed    
-
-
-def test_more_green():
-    def f(x):
-        z = x + 1
-        x2 = hint(x, concrete=True)
-        return z
-
-    hs = hannotate(f, [int])
-    assert isinstance(hs, SomeLLAbstractConstant)
-    assert hs.is_green()
-    assert not hs.is_fixed()
-
-def test_blue_simple_meth():
-    py.test.skip("with abstract containers this test explode in the cast_pointer annotation logic")
-    class Base(object):
-
-        def m(self):
-            raise NotImplementedError
-
-    class Concrete(Base):
-
-        def m(self):
-            return 42
-
-    def f(flag):
-        if flag:
-            o = Base()
-        else:
-            o = Concrete()
-        return o.m()
+        self.hannotate(f2, [], policy=P_OOPSPEC_NOVIRTUAL)    
 
-    hs = hannotate(f, [bool], policy=P_OOPSPEC)
 
+    def test_raise_and_catch_exc(self):
+        class E(Exception):
+            pass
+        def f(flag):
+            if flag:
+                raise E
+
+        def g(flag):
+            try:
+                f(flag)
+            except E:
+                return -1
+            return 0
+
+        hs = self.hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed
+
+        def f(flag):
+            if flag:
+                e = E()
+                e.a = 3
+                raise e
+
+        hs = self.hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)    
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.concretetype == lltype.Signed    
+
+
+    def test_more_green(self):
+        def f(x):
+            z = x + 1
+            x2 = hint(x, concrete=True)
+            return z
+
+        hs = self.hannotate(f, [int])
+        assert isinstance(hs, SomeLLAbstractConstant)
+        assert hs.is_green()
+        assert not hs.is_fixed()
+
+    def test_blue_simple_meth(self):
+        py.test.skip("with abstract containers this test explode in the cast_pointer annotation logic")
+        class Base(object):
+
+            def m(self):
+                raise NotImplementedError
+
+        class Concrete(Base):
+
+            def m(self):
+                return 42
+
+        def f(flag):
+            if flag:
+                o = Base()
+            else:
+                o = Concrete()
+            return o.m()
 
-def test_simple_meth():
-    class Base(object):
-        def m(self):
-            raise NotImplementedError
-        pass  # for inspect.getsource() bugs
-
-    class Concrete(Base):
-        def m(self):
-            return 42
-        pass  # for inspect.getsource() bugs
-
-    def f(flag):
-        if flag:
-            o = Base()
-        else:
-            o = Concrete()
-        return o.m()
+        hs = self.hannotate(f, [bool], policy=P_OOPSPEC)
 
-    hs = hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
 
+    def test_simple_meth(self):
+        class Base(object):
+            def m(self):
+                raise NotImplementedError
+            pass  # for inspect.getsource() bugs
+
+        class Concrete(Base):
+            def m(self):
+                return 42
+            pass  # for inspect.getsource() bugs
+
+        def f(flag):
+            if flag:
+                o = Base()
+            else:
+                o = Concrete()
+            return o.m()
 
-def test_green_isinstance():
-    class Base(object):
-        pass
-    class Concrete(Base):
-        pass
+        hs = self.hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
 
-    def f(o):
-        hint(o, concrete=True)
-        return isinstance(o, Concrete)
 
-    hs = hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
-    assert hs.is_green()
+    def test_green_isinstance(self):
+        class Base(object):
+            pass
+        class Concrete(Base):
+            pass
 
+        def f(o):
+            hint(o, concrete=True)
+            return isinstance(o, Concrete)
 
-def test_cast_pointer_keeps_deepfreeze():
+        hs = self.hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
+        assert hs.is_green()
 
-    class A(object):
-        pass
-    class B(A):
-        pass
-    
-    def getinstance(n):
-        if n:
-            return A()
-        else:
-            return B()
-    
-    def ll_function(n):
-        a = getinstance(n)
-        a = hint(a, promote=True)
-        a = hint(a, deepfreeze=True)
 
-        if isinstance(a, B):
-            return a
-        return None
+    def test_cast_pointer_keeps_deepfreeze(self):
 
-    hs = hannotate(ll_function, [int], policy=P_NOVIRTUAL)
-    assert hs.deepfrozen
+        class A(object):
+            pass
+        class B(A):
+            pass
 
+        def getinstance(n):
+            if n:
+                return A()
+            else:
+                return B()
 
-def test_concrete_fnptr_for_green_call():
+        def ll_function(n):
+            a = getinstance(n)
+            a = hint(a, promote=True)
+            a = hint(a, deepfreeze=True)
 
-    def h1(n):
-        return n * 10
-
-    def h2(n):
-        return n + 20
-
-    lst = [h1, h2]
-
-    def ll_function(n, m):
-        h = hint(lst, deepfreeze=True)[m]
-        res = h(n)
-        hint(res, concrete=True)   # so 'h' gets green, so 'm' gets green
-        return m
-
-    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
-    assert hs.is_green()
-
-
-def test_indirect_yellow_call():
-
-    def h1(n):
-        return 123
-
-    def h2(n):
-        return 456
-
-    lst = [h1, h2]
-
-    def ll_function(n, m):
-        h = hint(lst, deepfreeze=True)[m]
-        return h(n)
-
-    hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
-    assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_pure_red_call():
-    def h1(x):
-        return x-2
-    def h2(x):
-        return x*4
-    l = [h1, h2]
-    def f(n, x):
-        frozenl = hint(l, deepfreeze=True)
-        h = frozenl[n&1]
-        return h(x)
-
-    P = StopAtXPolicy(h1)
-    P.oopspec = True
-    P.entrypoint_returns_red = False
-    hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
-    assert not hs.is_green()
-    assert isinstance(hs, SomeLLAbstractConstant)
-
-    tsgraph = graphof(hannotator.translator, h2)
-    hs = hannotator.binding(tsgraph.getargs()[0])
-    assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_red_call():
-    class Stuff:
-        pass
-    stuff = Stuff()
-    def h1(x):
-        stuff.hello = 123
-        return x-2
-    def h2(x):
-        return x*4
-    l = [h1, h2]
-    def f(n, x):
-        frozenl = hint(l, deepfreeze=True)
-        h = frozenl[n&1]
-        return h(x)
-
-    P = StopAtXPolicy(h1)
-    P.oopspec = True
-    P.entrypoint_returns_red = False
-    hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
-    assert not hs.is_green()
-
-    tsgraph = graphof(hannotator.translator, h2)
-    hs = hannotator.binding(tsgraph.getargs()[0])
-    assert not hs.is_green()
-
-
-def test_indirect_sometimes_residual_pure_but_fixed_red_call():
-    def h1(x):
-        return x-2
-    def h2(x):
-        return x*4
-    l = [h1, h2]
-    def f(n, x):
-        frozenl = hint(l, deepfreeze=True)
-        h = frozenl[n&1]
-        z = h(x)
-        hint(z, concrete=True)
-        return z
-
-    P = StopAtXPolicy(h1)
-    P.oopspec = True
-    P.entrypoint_returns_red = False
-    hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
-    assert hs.is_green()
-
-    #tsgraph = graphof(hannotator.translator, h2)
-    #hs = hannotator.binding(tsgraph.getargs()[0])
-    #assert hs.is_green()
-
-    tsgraph = graphof(hannotator.translator, f)
-    hs = hannotator.binding(tsgraph.getargs()[0])
-    assert hs.is_green()
-    hs = hannotator.binding(tsgraph.getargs()[1])
-    assert hs.is_green()
-
-def test_ignore_nonjitted_path():
-    def f(n):
-        if we_are_jitted():
-            return 5
-        else:
-            return n
-    hs = hannotate(f, [int])
-    assert hs.is_green()
-
-    def g(n):
-        if not we_are_jitted():
-            return n
-        else:
-            return 5
-    hs = hannotate(g, [int])
-    assert hs.is_green()
-
-    def g(n):
-        if not we_are_jitted():
-            return n
-        else:
-            return 5
-    hs = hannotate(g, [int], backendoptimize=True)
-    assert hs.is_green()
-
-
-def test_substitute_graph():
-    class MetaG:
-        pass    # the details are only used by the timeshifter
-
-    def g(m):
-        return m * 17
-
-    def f(n, m):
-        x = g(n)
-        y = g(m)
-        hint(y, concrete=True)
-        return g(m)
-
-    class MyPolicy(HintAnnotatorPolicy):
-        entrypoint_returns_red = False
-        def look_inside_graph(self, graph):
-            if graph.func is g:
-                return MetaG   # replaces g with a meta-call to metafunc()
-            else:
-                return True
-
-    hs, hannotator = hannotate(f, [int, int], policy=MyPolicy(),
-                               annotator=True)
-    assert hs.is_green()
-    for graph in hannotator.translator.graphs:
-        assert 'int_mul' not in flowmodel.summary(graph)
-
-
-def test_cast_ptr_to_int():
-    GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
-    def f():
-        p = lltype.malloc(GCS1)
-        return lltype.cast_ptr_to_int(p)
-
-    hs = hannotate(f, [], policy=P_NOVIRTUAL)
-    assert not hs.is_green()
-
-def test_strange_green_result_after_red_switch():
-    py.test.skip("is this right?")
-    class LinkedRules(object):
-        _immutable_ = True
-        def __init__(self, data, next=None):
-            self.data = data
-            self.next = next
-
-        def find_applicable_rule(self, query):
-            # self is green, query isn't
-            # should the result really be green?
-            while self:
-                data = self.data
-                hint(data, concrete=True)
-                j = 0
-                if self.data == query:
-                    return self
-                self = self.next
+            if isinstance(a, B):
+                return a
             return None
 
-    chain = LinkedRules(1, LinkedRules(2, LinkedRules(0)))
-    def f(x):
-        rulechain = chain.find_applicable_rule(x)
-        return rulechain
-    hs = hannotate(f, [int], policy=P_OOPSPEC_NOVIRTUAL)
-    assert isinstance(hs, SomeLLAbstractVariable)
-
-def test_manual_marking_of_pure_functions():
-    d = {}
-    def h1(s):
-        try:
-            return d[s]
-        except KeyError:
-            d[s] = r = hash(s)
-            return r
-    h1._pure_function_ = True
-    def f(n):
-        hint(n, concrete=True)
-        if n == 0:
-            s = "abc"
-        else:
-            s = "123"
-        a = h1(s)
-        return a
-
-    P = StopAtXPolicy(h1)
-    P.oopspec = True
-    P.entrypoint_returns_red = False
-    hs = hannotate(f, [int], policy=P)
-    assert hs.is_green()
+        hs = self.hannotate(ll_function, [int], policy=P_NOVIRTUAL)
+        assert hs.deepfrozen
+
+
+    def test_concrete_fnptr_for_green_call(self):
+
+        def h1(n):
+            return n * 10
+
+        def h2(n):
+            return n + 20
+
+        lst = [h1, h2]
+
+        def ll_function(n, m):
+            h = hint(lst, deepfreeze=True)[m]
+            res = h(n)
+            hint(res, concrete=True)   # so 'h' gets green, so 'm' gets green
+            return m
+
+        hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+        assert hs.is_green()
+
+
+    def test_indirect_yellow_call(self):
+
+        def h1(n):
+            return 123
+
+        def h2(n):
+            return 456
+
+        lst = [h1, h2]
+
+        def ll_function(n, m):
+            h = hint(lst, deepfreeze=True)[m]
+            return h(n)
+
+        hs = self.hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+        assert not hs.is_green()
+
+
+    def test_indirect_sometimes_residual_pure_red_call(self):
+        def h1(x):
+            return x-2
+        def h2(x):
+            return x*4
+        l = [h1, h2]
+        def f(n, x):
+            frozenl = hint(l, deepfreeze=True)
+            h = frozenl[n&1]
+            return h(x)
+
+        P = StopAtXPolicy(h1)
+        P.oopspec = True
+        P.entrypoint_returns_red = False
+        hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+        assert not hs.is_green()
+        assert isinstance(hs, SomeLLAbstractConstant)
+
+        tsgraph = graphof(hannotator.translator, h2)
+        hs = hannotator.binding(tsgraph.getargs()[0])
+        assert not hs.is_green()
+
+
+    def test_indirect_sometimes_residual_red_call(self):
+        class Stuff:
+            pass
+        stuff = Stuff()
+        def h1(x):
+            stuff.hello = 123
+            return x-2
+        def h2(x):
+            return x*4
+        l = [h1, h2]
+        def f(n, x):
+            frozenl = hint(l, deepfreeze=True)
+            h = frozenl[n&1]
+            return h(x)
+
+        P = StopAtXPolicy(h1)
+        P.oopspec = True
+        P.entrypoint_returns_red = False
+        hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+        assert not hs.is_green()
+
+        tsgraph = graphof(hannotator.translator, h2)
+        hs = hannotator.binding(tsgraph.getargs()[0])
+        assert not hs.is_green()
+
+
+    def test_indirect_sometimes_residual_pure_but_fixed_red_call(self):
+        def h1(x):
+            return x-2
+        def h2(x):
+            return x*4
+        l = [h1, h2]
+        def f(n, x):
+            frozenl = hint(l, deepfreeze=True)
+            h = frozenl[n&1]
+            z = h(x)
+            hint(z, concrete=True)
+            return z
+
+        P = StopAtXPolicy(h1)
+        P.oopspec = True
+        P.entrypoint_returns_red = False
+        hs, hannotator = self.hannotate(f, [int, int], policy=P, annotator=True)
+        assert hs.is_green()
+
+        #tsgraph = graphof(hannotator.translator, h2)
+        #hs = hannotator.binding(tsgraph.getargs()[0])
+        #assert hs.is_green()
+
+        tsgraph = graphof(hannotator.translator, f)
+        hs = hannotator.binding(tsgraph.getargs()[0])
+        assert hs.is_green()
+        hs = hannotator.binding(tsgraph.getargs()[1])
+        assert hs.is_green()
+
+    def test_ignore_nonjitted_path(self):
+        def f(n):
+            if we_are_jitted():
+                return 5
+            else:
+                return n
+        hs = self.hannotate(f, [int])
+        assert hs.is_green()
+
+        def g(n):
+            if not we_are_jitted():
+                return n
+            else:
+                return 5
+        hs = self.hannotate(g, [int])
+        assert hs.is_green()
+
+        def g(n):
+            if not we_are_jitted():
+                return n
+            else:
+                return 5
+        hs = self.hannotate(g, [int], backendoptimize=True)
+        assert hs.is_green()
+
+
+    def test_substitute_graph(self):
+        class MetaG:
+            pass    # the details are only used by the timeshifter
+
+        def g(m):
+            return m * 17
+
+        def f(n, m):
+            x = g(n)
+            y = g(m)
+            hint(y, concrete=True)
+            return g(m)
+
+        class MyPolicy(HintAnnotatorPolicy):
+            entrypoint_returns_red = False
+            def look_inside_graph(self, graph):
+                if graph.func is g:
+                    return MetaG   # replaces g with a meta-call to metafunc()
+                else:
+                    return True
+
+        hs, hannotator = self.hannotate(f, [int, int], policy=MyPolicy(),
+                                   annotator=True)
+        assert hs.is_green()
+        for graph in hannotator.translator.graphs:
+            assert 'int_mul' not in flowmodel.summary(graph)
+
+    def test_strange_green_result_after_red_switch(self):
+        py.test.skip("is this right?")
+        class LinkedRules(object):
+            _immutable_ = True
+            def __init__(self, data, next=None):
+                self.data = data
+                self.next = next
+
+            def find_applicable_rule(self, query):
+                # self is green, query isn't
+                # should the result really be green?
+                while self:
+                    data = self.data
+                    hint(data, concrete=True)
+                    j = 0
+                    if self.data == query:
+                        return self
+                    self = self.next
+                return None
+
+        chain = LinkedRules(1, LinkedRules(2, LinkedRules(0)))
+        def f(x):
+            rulechain = chain.find_applicable_rule(x)
+            return rulechain
+        hs = self.hannotate(f, [int], policy=P_OOPSPEC_NOVIRTUAL)
+        assert isinstance(hs, SomeLLAbstractVariable)
+
+    def test_manual_marking_of_pure_functions(self):
+        d = {}
+        def h1(s):
+            try:
+                return d[s]
+            except KeyError:
+                d[s] = r = hash(s)
+                return r
+        h1._pure_function_ = True
+        def f(n):
+            hint(n, concrete=True)
+            if n == 0:
+                s = "abc"
+            else:
+                s = "123"
+            a = h1(s)
+            return a
+
+        P = StopAtXPolicy(h1)
+        P.oopspec = True
+        P.entrypoint_returns_red = False
+        hs = self.hannotate(f, [int], policy=P)
+        assert hs.is_green()
+
+class TestLLType(BaseAnnotatorTest):
+    type_system = 'lltype'
+
+    malloc = property(lambda self: lltype.malloc)
+    
+    def make_struct(self, name, *fields, **kwds):
+        return lltype.GcStruct(name, *fields, **kwds)
+
+    def annotate_struct(self, S):
+        return annmodel.SomePtr(lltype.Ptr(S))
+
+    def test_simple_cast_pointer(self):
+        GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
+        GCS2 = lltype.GcStruct('s2', ('sub', GCS1), ('y', lltype.Signed))
+        PGCS1 = lltype.Ptr(GCS1)
+        PGCS2 = lltype.Ptr(GCS2)
+        def ll1():
+            s2 = lltype.malloc(GCS2)
+            return lltype.cast_pointer(PGCS1, s2)
+        hs = self.hannotate(ll1, [])
+        assert isinstance(hs, SomeLLAbstractContainer)
+        assert hs.concretetype == PGCS1
+        def ll1():
+            s2 = lltype.malloc(GCS2)
+            s1 = s2.sub
+            return lltype.cast_pointer(PGCS2, s1)
+        hs = self.hannotate(ll1, [])
+        assert isinstance(hs, SomeLLAbstractContainer)
+        assert hs.concretetype == PGCS2
+
+    def test_getarrayitem(self):
+        A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
+        a = lltype.malloc(A, 10)
+        def ll1(n):
+            v = a[n]
+            v = hint(v, concrete=True)
+            return v
+        hs, ha = self.hannotate(ll1, [int], annotator=True)
+        assert hs.eager_concrete
+        g1 = graphof(ha.translator, ll1)
+        hs_n = ha.binding(g1.getargs()[0])
+        assert hs_n.origins.keys()[0].fixed
+
+    def test_getvarrayitem(self):
+        A = lltype.GcArray(lltype.Signed, hints={'immutable': True})
+        def ll1(n):
+            a = lltype.malloc(A, 10)
+            v = a[n]
+            v = hint(v, concrete=True)
+            return v
+        hs, ha = self.hannotate(ll1, [int], annotator=True)
+        assert hs.eager_concrete
+        g1 = graphof(ha.translator, ll1)
+        hs_n = ha.binding(g1.getargs()[0])
+        assert hs_n.origins.keys()[0].fixed
+
+    def test_degenerated_merge_substructure(self):
+        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 = self.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_degenerated_merge_cross_substructure(self):
+        py.test.skip("no longer a valid test")
+        from pypy.rlib import objectmodel
+        S = lltype.Struct('S', ('n', lltype.Signed))
+        T = lltype.GcStruct('T', ('s', S), ('s1', S), ('n', lltype.Float))
+
+        def ll_function(flag):
+            t = lltype.malloc(T)
+            t.s.n = 3
+            t.s1.n = 3
+            if flag:
+                s = t.s
+            else:
+                s = t.s1
+            objectmodel.keepalive_until_here(t)
+            return s, t
+        hs = self.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_cast_ptr_to_int(self):
+        GCS1 = lltype.GcStruct('s1', ('x', lltype.Signed))
+        def f():
+            p = lltype.malloc(GCS1)
+            return lltype.cast_ptr_to_int(p)
+
+        hs = self.hannotate(f, [], policy=P_NOVIRTUAL)
+        assert not hs.is_green()
+
+
+class TestOOType(BaseAnnotatorTest):
+    type_system = 'ootype'
+
+    malloc = property(lambda self: ootype.new)
+
+    def make_struct(self, name, *fields, **kwds):
+        fields = dict(fields)
+        hints = kwds.pop('hints', None)
+        if hints:
+            kwds['_hints'] = hints
+        return ootype.Instance(name, ootype.ROOT, fields, **kwds)
+
+    def annotate_struct(self, S):
+        return annmodel.SomeOOInstance(S)
+
+    def skip_policy(self):
+        py.test.skip('fixme? (This policy is not relevant for now)')
+
+    test_simple_list_operations = skip_policy
+    test_some_more_list_operations = skip_policy
+    test_make_a_list = skip_policy
+    test_simple_struct_malloc = skip_policy
+    test_container_union = skip_policy
+    test_specialize_deepfreeze_calls = skip_policy
+    test_deepfreeze_variables = skip_policy
+    test_cast_pointer_keeps_deepfreeze = skip_policy
+    test_concrete_fnptr_for_green_call = skip_policy

Modified: pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/jit/hintannotator/test/test_toy.py	Sat Dec 15 13:57:29 2007
@@ -1,20 +1,27 @@
-from pypy.jit.hintannotator.test.test_annotator import hannotate, P_OOPSPEC
-from pypy.jit.hintannotator.test.test_annotator import P_OOPSPEC_NOVIRTUAL
+from pypy.jit.hintannotator.test.test_annotator import AbstractAnnotatorTest
+from pypy.jit.hintannotator.test.test_annotator import P_OOPSPEC, P_OOPSPEC_NOVIRTUAL
 
+class BaseToyTest(AbstractAnnotatorTest):
+    def test_hannotate_tl(self):
+        from pypy.jit.tl import tl
+        self.hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC)
 
-def test_hannotate_tl():
-    from pypy.jit.tl import tl
-    hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC)
-
-def test_hannotate_tl_novirtual():
-    from pypy.jit.tl import tl
-    hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL)
-
-def test_hannotate_tlr_novirtual():
-    from pypy.jit.tl import tlr
-    hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL)
-
-def test_hannotate_tlc_novirtual():
-    from pypy.jit.tl import tlc
-    hannotate(tlc.interp_without_call, [str, int, int],
-              policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True)
+    def test_hannotate_tl_novirtual(self):
+        from pypy.jit.tl import tl
+        self.hannotate(tl.interp, [str, int, int], policy=P_OOPSPEC_NOVIRTUAL)
+
+    def test_hannotate_tlr_novirtual(self):
+        from pypy.jit.tl import tlr
+        self.hannotate(tlr.interpret, [str, int], policy=P_OOPSPEC_NOVIRTUAL)
+
+    def test_hannotate_tlc_novirtual(self):
+        from pypy.jit.tl import tlc
+        self.hannotate(tlc.interp_without_call, [str, int, int],
+                       policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True)
+
+class TestLLType(BaseToyTest):
+    type_system = 'lltype'
+
+## XXX: all tests fail :-(
+##class TestOOType(BaseToyTest):
+##    type_system = 'ootype'

Modified: pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/module/__builtin__/__init__.py	Sat Dec 15 13:57:29 2007
@@ -60,9 +60,6 @@
         'buffer'        : 'app_buffer.buffer',
         'reload'        : 'app_misc.reload',
 
-        'set'           : 'app_sets.set',
-        'frozenset'     : 'app_sets.frozenset',
-
         '__filestub'    : 'app_file_stub.file',
     }
 
@@ -80,8 +77,8 @@
         'open'          : 'state.get(space).w_file',
 
         # old-style classes dummy support
-        '_classobj'     : 'space.w_classobj',
-        '_instance'     : 'space.w_instance',
+        '_classobj'     : 'interp_classobj.W_ClassObject',
+        '_instance'     : 'interp_classobj.W_InstanceObject',
         # default __metaclass__
         '__metaclass__' : '(space.w_type)',
 

Modified: pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/module/_random/interp_random.py	Sat Dec 15 13:57:29 2007
@@ -110,7 +110,7 @@
     getrandbits.unwrap_spec = ['self', ObjSpace, int]
 
 
-W_Random.typedef = TypeDef("W_Random",
+W_Random.typedef = TypeDef("Random",
     __new__ = interp2app(descr_new__),
     random = interp2app(W_Random.random),
     seed = interp2app(W_Random.seed),

Modified: pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/module/crypt/interp_crypt.py	Sat Dec 15 13:57:29 2007
@@ -2,8 +2,12 @@
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
+import sys
 
-eci = ExternalCompilationInfo(libraries=['crypt'])
+if sys.platform.startswith('darwin'):
+    eci = ExternalCompilationInfo()
+else:
+    eci = ExternalCompilationInfo(libraries=['crypt'])
 c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP,
                           compilation_info=eci, threadsafe=False)
 

Modified: pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/objspace/std/objspace.py	Sat Dec 15 13:57:29 2007
@@ -282,15 +282,8 @@
     def setup_old_style_classes(self):
         """NOT_RPYTHON"""
         # sanity check that this approach is working and is not too late
-        w_mod, w_dic = self.create_builtin_module('_classobj.py', 'classobj')
-        w_purify = self.getitem(w_dic, self.wrap('purify'))
-        w_classobj = self.getitem(w_dic, self.wrap('classobj'))
-        w_instance = self.getitem(w_dic, self.wrap('instance'))
-        self.call_function(w_purify)
-        assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_classobj'))),"app-level code has seen dummy old style classes"
-        assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_instance'))),"app-level code has seen dummy old style classes"
-        self.w_classobj = w_classobj
-        self.w_instance = w_instance
+        self.w_classobj = self.getattr(self.builtin, self.wrap('_classobj'))
+        self.w_instance = self.getattr(self.builtin, self.wrap('_instance'))
 
     def create_builtin_module(self, pyname, publicname):
         """NOT_RPYTHON

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/llmemory.py	Sat Dec 15 13:57:29 2007
@@ -61,7 +61,8 @@
                 assert index.startswith('item')    # itemN => N
                 index = int(index[4:])
             return parent.getitem(index + self.repeat)._as_ptr()
-        elif isinstance(A, lltype.FixedSizeArray) and A.OF == self.TYPE:
+        elif (isinstance(A, lltype.FixedSizeArray) and
+              array_item_type_match(A.OF, self.TYPE)):
             # for array of primitives or pointers
             return lltype.direct_ptradd(firstitemptr, self.repeat)
         else:
@@ -191,7 +192,7 @@
         return '< ArrayItemsOffset %r >' % (self.TYPE,)
 
     def ref(self, arrayptr):
-        assert lltype.typeOf(arrayptr).TO == self.TYPE
+        assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
         if isinstance(self.TYPE.OF, lltype.ContainerType):
             # XXX this doesn't support empty arrays
             o = arrayptr._obj.getitem(0)
@@ -228,7 +229,7 @@
         return '< ArrayLengthOffset %r >' % (self.TYPE,)
 
     def ref(self, arrayptr):
-        assert lltype.typeOf(arrayptr).TO == self.TYPE
+        assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
         return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
 
 
@@ -405,6 +406,21 @@
 # GCREF is similar to Address but it is GC-aware
 GCREF = lltype.Ptr(lltype.GcOpaqueType('GCREF'))
 
+# A placeholder for any type that is a GcArray of pointers.
+# This can be used in the symbolic offsets above to access such arrays
+# in a generic way.
+GCARRAY_OF_PTR = lltype.GcArray(GCREF, hints={'placeholder': True})
+gcarrayofptr_lengthoffset = ArrayLengthOffset(GCARRAY_OF_PTR)
+gcarrayofptr_itemsoffset = ArrayItemsOffset(GCARRAY_OF_PTR)
+gcarrayofptr_singleitemoffset = ItemOffset(GCARRAY_OF_PTR.OF)
+def array_type_match(A1, A2):
+    return A1 == A2 or (A2 == GCARRAY_OF_PTR and
+                        isinstance(A1, lltype.GcArray) and
+                        isinstance(A1.OF, lltype.Ptr) and
+                        not A1._hints.get('nolength'))
+def array_item_type_match(T1, T2):
+    return T1 == T2 or (T2 == GCREF and isinstance(T1, lltype.Ptr))
+
 
 class _fakeaccessor(object):
     def __init__(self, addr):

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/lltypesystem/test/test_llmemory.py	Sat Dec 15 13:57:29 2007
@@ -524,3 +524,21 @@
     assert weakref_deref(lltype.Ptr(S), w) == lltype.nullptr(S)
     assert weakref_deref(lltype.Ptr(S1), w) == lltype.nullptr(S1)
 
+def test_generic_gcarray_of_ptr():
+    S1 = lltype.GcStruct('S1', ('x', lltype.Signed))
+    A1 = lltype.GcArray(lltype.Ptr(S1))
+    A2 = lltype.GcArray(lltype.Ptr(A1))
+    a2 = lltype.malloc(A2, 3)
+    a2[1] = lltype.malloc(A1, 4)
+    a2[1][2] = lltype.malloc(S1)
+    a2[1][2].x = -33
+
+    adr = cast_ptr_to_adr(a2)
+    assert (adr + gcarrayofptr_lengthoffset).signed[0] == 3
+    adr += gcarrayofptr_itemsoffset
+    adr += gcarrayofptr_singleitemoffset
+    adr = adr.address[0]    # => a2[1]
+    assert (adr + gcarrayofptr_lengthoffset).signed[0] == 4
+    adr += gcarrayofptr_itemsoffset + 2 * gcarrayofptr_singleitemoffset
+    adr = adr.address[0]    # => s2[1][2]
+    assert (adr + FieldOffset(S1, 'x')).signed[0] == -33

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gc/base.py	Sat Dec 15 13:57:29 2007
@@ -8,6 +8,7 @@
     needs_zero_gc_pointers = True
 
     def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
+                            is_gcarrayofgcptr,
                             getfinalizer,
                             offsets_to_gc_pointers,
                             fixed_size, varsize_item_sizes,
@@ -18,6 +19,7 @@
         self.getfinalizer = getfinalizer
         self.is_varsize = is_varsize
         self.has_gcptr_in_varsize = has_gcptr_in_varsize
+        self.is_gcarrayofgcptr = is_gcarrayofgcptr
         self.offsets_to_gc_pointers = offsets_to_gc_pointers
         self.fixed_size = fixed_size
         self.varsize_item_sizes = varsize_item_sizes
@@ -115,6 +117,15 @@
         Typically, 'callback' is a bound method and 'arg' can be None.
         """
         typeid = self.get_type_id(obj)
+        if self.is_gcarrayofgcptr(typeid):
+            # a performance shortcut for GcArray(gcptr)
+            length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0]
+            item = obj + llmemory.gcarrayofptr_itemsoffset
+            while length > 0:
+                callback(item, arg)
+                item += llmemory.gcarrayofptr_singleitemoffset
+                length -= 1
+            return
         offsets = self.offsets_to_gc_pointers(typeid)
         i = 0
         while i < len(offsets):
@@ -125,14 +136,13 @@
             length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
             offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
             itemlength = self.varsize_item_sizes(typeid)
-            i = 0
-            while i < length:
+            while length > 0:
                 j = 0
                 while j < len(offsets):
                     callback(item + offsets[j], arg)
                     j += 1
-                i += 1
                 item += itemlength
+                length -= 1
     trace._annspecialcase_ = 'specialize:arg(2)'
 
 

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/framework.py	Sat Dec 15 13:57:29 2007
@@ -91,8 +91,6 @@
         print "found %s initializing stores in %s" % (len(result), graph.name)
     return result
 
-ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
-
 class FrameworkGCTransformer(GCTransformer):
     use_stackless = False
     root_stack_depth = 163840
@@ -111,75 +109,21 @@
             # for regular translation: pick the GC from the config
             GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
 
-        self.FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC)
-        class GCData(object):
-            # types of the GC information tables
-            OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
-            TYPE_INFO = lltype.Struct("type_info",
-                ("isvarsize",   lltype.Bool),
-                ("gcptrinvarsize", lltype.Bool),
-                ("finalizer",   self.FINALIZERTYPE),
-                ("fixedsize",   lltype.Signed),
-                ("ofstoptrs",   lltype.Ptr(OFFSETS_TO_GC_PTR)),
-                ("varitemsize", lltype.Signed),
-                ("ofstovar",    lltype.Signed),
-                ("ofstolength", lltype.Signed),
-                ("varofstoptrs",lltype.Ptr(OFFSETS_TO_GC_PTR)),
-                ("weakptrofs",  lltype.Signed),
-                )
-            TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
-
-        def q_is_varsize(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].isvarsize
-
-        def q_has_gcptr_in_varsize(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].gcptrinvarsize
-
-        def q_finalizer(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].finalizer
-
-        def q_offsets_to_gc_pointers(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].ofstoptrs
-
-        def q_fixed_size(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].fixedsize
-
-        def q_varsize_item_sizes(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].varitemsize
-
-        def q_varsize_offset_to_variable_part(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].ofstovar
-
-        def q_varsize_offset_to_length(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].ofstolength
-
-        def q_varsize_offsets_to_gcpointers_in_var_part(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].varofstoptrs
-
-        def q_weakpointer_offset(typeid):
-            ll_assert(typeid > 0, "invalid type_id")
-            return gcdata.type_info_table[typeid].weakptrofs
-
         self.layoutbuilder = TransformerLayoutBuilder(self)
         self.get_type_id = self.layoutbuilder.get_type_id
 
-        gcdata = GCData()
         # set up dummy a table, to be overwritten with the real one in finish()
-        gcdata.type_info_table = lltype.malloc(GCData.TYPE_INFO_TABLE, 0,
-                                               immortal=True)
+        type_info_table = lltype._ptr(
+            lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE),
+            "delayed!type_info_table", solid=True)
+        gcdata = gctypelayout.GCData(type_info_table)
+
         # initialize the following two fields with a random non-NULL address,
         # to make the annotator happy.  The fields are patched in finish()
-        # to point to a real array (not 'static_roots', another one).
-        a_random_address = llmemory.cast_ptr_to_adr(gcdata.type_info_table)
+        # to point to a real array.
+        foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1),
+                            immortal=True, zero=True)
+        a_random_address = llmemory.cast_ptr_to_adr(foo)
         gcdata.static_root_start = a_random_address      # patched in finish()
         gcdata.static_root_nongcstart = a_random_address # patched in finish()
         gcdata.static_root_end = a_random_address        # patched in finish()
@@ -190,6 +134,7 @@
 
         StackRootIterator = self.build_stack_root_iterator()
         gcdata.gc = GCClass(AddressLinkedList, get_roots=StackRootIterator, **GC_PARAMS)
+        gcdata.set_query_functions(gcdata.gc)
         self.num_pushs = 0
         self.write_barrier_calls = 0
 
@@ -197,29 +142,12 @@
             # run-time initialization code
             StackRootIterator.setup_root_stack()
             gcdata.gc.setup()
-            gcdata.gc.set_query_functions(
-                q_is_varsize,
-                q_has_gcptr_in_varsize,
-                q_finalizer,
-                q_offsets_to_gc_pointers,
-                q_fixed_size,
-                q_varsize_item_sizes,
-                q_varsize_offset_to_variable_part,
-                q_varsize_offset_to_length,
-                q_varsize_offsets_to_gcpointers_in_var_part,
-                q_weakpointer_offset)
 
         bk = self.translator.annotator.bookkeeper
 
         # the point of this little dance is to not annotate
-        # self.gcdata.type_info_table as a constant.
-        data_classdef = bk.getuniqueclassdef(GCData)
-        data_classdef.generalize_attr(
-            'type_info_table',
-            annmodel.SomePtr(lltype.Ptr(GCData.TYPE_INFO_TABLE)))
-        data_classdef.generalize_attr(
-            'static_roots',
-            annmodel.SomePtr(lltype.Ptr(lltype.Array(llmemory.Address))))
+        # self.gcdata.static_root_xyz as constants. XXX is it still needed??
+        data_classdef = bk.getuniqueclassdef(gctypelayout.GCData)
         data_classdef.generalize_attr(
             'static_root_start',
             annmodel.SomeAddress())
@@ -496,9 +424,10 @@
 
         # replace the type_info_table pointer in gcdata -- at this point,
         # the database is in principle complete, so it has already seen
-        # the old (empty) array.  We need to force it to consider the new
-        # array now.  It's a bit hackish as the old empty array will also
-        # be generated in the C source, but that's a rather minor problem.
+        # the delayed pointer.  We need to force it to consider the new
+        # array now.
+
+        self.gcdata.type_info_table._become(table)
 
         # XXX because we call inputconst already in replace_malloc, we can't
         # modify the instance, we have to modify the 'rtyped instance'
@@ -508,8 +437,6 @@
             self.gcdata)
         r_gcdata = self.translator.rtyper.getrepr(s_gcdata)
         ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value
-        ll_instance.inst_type_info_table = table
-        #self.gcdata.type_info_table = table
 
         addresses_of_static_ptrs = (
             self.layoutbuilder.addresses_of_static_ptrs +
@@ -528,7 +455,7 @@
         ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * (len(ll_static_roots_inside) - additional_ptrs)
 
         newgcdependencies = []
-        newgcdependencies.append(table)
+        newgcdependencies.append(self.gcdata.type_info_table)
         newgcdependencies.append(ll_static_roots_inside)
         self.write_typeid_list()
         return newgcdependencies
@@ -543,6 +470,7 @@
         all.sort()
         for typeid, TYPE in all:
             f.write("%s %s\n" % (typeid, TYPE))
+        f.close()
 
     def transform_graph(self, graph):
         if self.write_barrier_ptr:
@@ -573,7 +501,7 @@
 
         c_type_id = rmodel.inputconst(lltype.Signed, type_id)
         info = self.layoutbuilder.type_info_list[type_id]
-        c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+        c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
         has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE))
         c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer)
 
@@ -592,8 +520,8 @@
                     c_has_finalizer, rmodel.inputconst(lltype.Bool, False)]
         else:
             v_length = op.args[-1]
-            c_ofstolength = rmodel.inputconst(lltype.Signed, info['ofstolength'])
-            c_varitemsize = rmodel.inputconst(lltype.Signed, info['varitemsize'])
+            c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
+            c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
             malloc_ptr = self.malloc_varsize_clear_ptr
 ##             if op.opname.startswith('zero'):
 ##                 malloc_ptr = self.malloc_varsize_clear_ptr
@@ -624,7 +552,7 @@
 
         c_type_id = rmodel.inputconst(lltype.Signed, type_id)
         info = self.layoutbuilder.type_info_list[type_id]
-        c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+        c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
         has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE))
         assert not has_finalizer
 
@@ -635,8 +563,8 @@
             args = [self.c_const_gc, v_coallocator, c_type_id, c_size]
         else:
             v_length = op.args[-1]
-            c_ofstolength = rmodel.inputconst(lltype.Signed, info['ofstolength'])
-            c_varitemsize = rmodel.inputconst(lltype.Signed, info['varitemsize'])
+            c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength)
+            c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize)
             malloc_ptr = self.coalloc_varsize_clear_ptr
             args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size,
                     c_varitemsize, c_ofstolength]
@@ -698,7 +626,7 @@
 
         c_type_id = rmodel.inputconst(lltype.Signed, type_id)
         info = self.layoutbuilder.type_info_list[type_id]
-        c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
+        c_size = rmodel.inputconst(lltype.Signed, info.fixedsize)
         malloc_ptr = self.malloc_fixedsize_ptr
         c_has_finalizer = rmodel.inputconst(lltype.Bool, False)
         c_has_weakptr = c_can_collect = rmodel.inputconst(lltype.Bool, True)
@@ -856,31 +784,9 @@
                                                     [llmemory.Address],
                                                     lltype.Void)
         else:
-            fptr = lltype.nullptr(ADDRESS_VOID_FUNC)
+            fptr = lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO)
         return fptr
 
-    def offsets2table(self, offsets, TYPE):
-        try:
-            return self.offsettable_cache[TYPE]
-        except KeyError:
-            gcdata = self.transformer.gcdata
-            cachedarray = lltype.malloc(gcdata.OFFSETS_TO_GC_PTR,
-                                        len(offsets), immortal=True)
-            for i, value in enumerate(offsets):
-                cachedarray[i] = value
-            self.offsettable_cache[TYPE] = cachedarray
-            return cachedarray
-
-    def flatten_table(self):
-        self.can_add_new_types = False
-        table = lltype.malloc(self.transformer.gcdata.TYPE_INFO_TABLE,
-                              len(self.type_info_list), immortal=True)
-        for tableentry, newcontent in zip(table, self.type_info_list):
-            for key, value in newcontent.items():
-                setattr(tableentry, key, value)
-        self.offsettable_cache = None
-        return table
-
 
 def gen_zero_gc_pointers(TYPE, v, llops, previous_steps=None):
     if previous_steps is None:

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctransform/transform.py	Sat Dec 15 13:57:29 2007
@@ -279,7 +279,8 @@
         self.need_minimal_transform(graph)
         if inline:
             self.graphs_to_inline[graph] = True
-        return self.mixlevelannotator.graph2delayed(graph)
+        FUNCTYPE = lltype.FuncType(ll_args, ll_result)
+        return self.mixlevelannotator.graph2delayed(graph, FUNCTYPE=FUNCTYPE)
 
     def inittime_helper(self, ll_helper, ll_args, ll_result, inline=True):
         ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=inline)

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gctypelayout.py	Sat Dec 15 13:57:29 2007
@@ -1,13 +1,199 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
+from pypy.rlib.debug import ll_assert
+
+
+class GCData(object):
+    """The GC information tables, and the query functions that the GC
+    calls to decode their content.  The encoding of this information
+    is done by encode_type_shape().  These two places should be in sync,
+    obviously, but in principle no other code should depend on the
+    details of the encoding in TYPE_INFO.
+    """
+    _alloc_flavor_ = 'raw'
+
+    OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
+    ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
+    FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC)
+
+    # structure describing the layout of a typeid
+    TYPE_INFO = lltype.Struct("type_info",
+        ("finalizer",      FINALIZERTYPE),
+        ("fixedsize",      lltype.Signed),
+        ("ofstoptrs",      lltype.Ptr(OFFSETS_TO_GC_PTR)),
+        ("varitemsize",    lltype.Signed),
+        ("ofstovar",       lltype.Signed),
+        ("ofstolength",    lltype.Signed),
+        ("varofstoptrs",   lltype.Ptr(OFFSETS_TO_GC_PTR)),
+        ("weakptrofs",     lltype.Signed),
+        )
+    TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
+
+    def __init__(self, type_info_table):
+        self.type_info_table = type_info_table
+        # 'type_info_table' is a list of TYPE_INFO structures when
+        # running with gcwrapper, or a real TYPE_INFO_TABLE after
+        # the gctransformer.
+
+    def q_is_varsize(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return (typeid & T_IS_FIXSIZE) == 0
+
+    def q_has_gcptr_in_varsize(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return (typeid & (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE)) == 0
+
+    def q_is_gcarrayofgcptr(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return (typeid &
+                (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY)) == 0
+
+    def q_finalizer(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].finalizer
+
+    def q_offsets_to_gc_pointers(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].ofstoptrs
+
+    def q_fixed_size(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].fixedsize
+
+    def q_varsize_item_sizes(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].varitemsize
+
+    def q_varsize_offset_to_variable_part(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].ofstovar
+
+    def q_varsize_offset_to_length(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].ofstolength
+
+    def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].varofstoptrs
+
+    def q_weakpointer_offset(self, typeid):
+        ll_assert(typeid > 0, "invalid type_id")
+        return self.type_info_table[typeid].weakptrofs
+
+    def set_query_functions(self, gc):
+        gc.set_query_functions(
+            self.q_is_varsize,
+            self.q_has_gcptr_in_varsize,
+            self.q_is_gcarrayofgcptr,
+            self.q_finalizer,
+            self.q_offsets_to_gc_pointers,
+            self.q_fixed_size,
+            self.q_varsize_item_sizes,
+            self.q_varsize_offset_to_variable_part,
+            self.q_varsize_offset_to_length,
+            self.q_varsize_offsets_to_gcpointers_in_var_part,
+            self.q_weakpointer_offset)
+
+# For the q_xxx functions that return flags, we use bit patterns
+# in the typeid instead of entries in the type_info_table.  The
+# following flag combinations are used (the idea being that it's
+# very fast on CPUs to check if all flags in a set are all zero):
+
+#   * if T_IS_FIXSIZE is set, the gc object is not var-sized
+#   * if T_IS_FIXSIZE and T_NO_GCPTR_IN_VARSIZE are both cleared,
+#           there are gc ptrs in the var-sized part
+#   * if T_IS_FIXSIZE, T_NO_GCPTR_IN_VARSIZE and T_NOT_SIMPLE_GCARRAY
+#           are all cleared, the shape is just like GcArray(gcptr)
+
+T_IS_FIXSIZE          = 0x4
+T_NO_GCPTR_IN_VARSIZE = 0x2
+T_NOT_SIMPLE_GCARRAY  = 0x1
+
+def get_typeid_bitmask(TYPE):
+    """Return the bits that we would like to be set or cleared in the type_id
+    corresponding to TYPE.  This returns (mask, expected_value), where
+    the condition is that 'type_id & mask == expected_value'.
+    """
+    if not TYPE._is_varsize():
+        return (T_IS_FIXSIZE, T_IS_FIXSIZE)     # not var-sized
+
+    if (isinstance(TYPE, lltype.GcArray)
+        and isinstance(TYPE.OF, lltype.Ptr)
+        and TYPE.OF.TO._gckind == 'gc'):
+        # a simple GcArray(gcptr)
+        return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY, 0)
+
+    if isinstance(TYPE, lltype.Struct):
+        ARRAY = TYPE._flds[TYPE._arrayfld]
+    else:
+        ARRAY = TYPE
+    assert isinstance(ARRAY, lltype.Array)
+    if ARRAY.OF != lltype.Void and len(offsets_to_gc_pointers(ARRAY.OF)) > 0:
+        # var-sized, with gc pointers in the variable part
+        return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE|T_NOT_SIMPLE_GCARRAY,
+                T_NOT_SIMPLE_GCARRAY)
+    else:
+        # var-sized, but no gc pointer in the variable part
+        return (T_IS_FIXSIZE|T_NO_GCPTR_IN_VARSIZE, T_NO_GCPTR_IN_VARSIZE)
+
+
+def encode_type_shape(builder, info, TYPE):
+    """Encode the shape of the TYPE into the TYPE_INFO structure 'info'."""
+    offsets = offsets_to_gc_pointers(TYPE)
+    info.ofstoptrs = builder.offsets2table(offsets, TYPE)
+    info.finalizer = builder.make_finalizer_funcptr_for_type(TYPE)
+    info.weakptrofs = weakpointer_offset(TYPE)
+    if not TYPE._is_varsize():
+        #info.isvarsize = False
+        #info.gcptrinvarsize = False
+        info.fixedsize = llarena.round_up_for_allocation(
+            llmemory.sizeof(TYPE))
+        info.ofstolength = -1
+        # note about round_up_for_allocation(): in the 'info' table
+        # we put a rounded-up size only for fixed-size objects.  For
+        # varsize ones, the GC must anyway compute the size at run-time
+        # and round up that result.
+    else:
+        #info.isvarsize = True
+        info.fixedsize = llmemory.sizeof(TYPE, 0)
+        if isinstance(TYPE, lltype.Struct):
+            ARRAY = TYPE._flds[TYPE._arrayfld]
+            ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
+            info.ofstolength = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
+            if ARRAY.OF != lltype.Void:
+                info.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
+            else:
+                info.fixedsize = ofs1 + llmemory.sizeof(lltype.Signed)
+            # XXX we probably don't need isrpystring any more
+            if ARRAY._hints.get('isrpystring'):
+                info.fixedsize = llmemory.sizeof(TYPE, 1)
+        else:
+            ARRAY = TYPE
+            info.ofstolength = llmemory.ArrayLengthOffset(ARRAY)
+            if ARRAY.OF != lltype.Void:
+                info.ofstovar = llmemory.itemoffsetof(TYPE, 0)
+            else:
+                info.fixedsize = (llmemory.ArrayLengthOffset(ARRAY) +
+                                  llmemory.sizeof(lltype.Signed))
+        assert isinstance(ARRAY, lltype.Array)
+        if ARRAY.OF != lltype.Void:
+            offsets = offsets_to_gc_pointers(ARRAY.OF)
+        else:
+            offsets = ()
+        info.varofstoptrs = builder.offsets2table(offsets, ARRAY.OF)
+        info.varitemsize = llmemory.sizeof(ARRAY.OF)
+        #info.gcptrinvarsize = len(offsets) > 0
+    #info.gcarrayofgcptr = (isinstance(TYPE, lltype.GcArray)
+    #                       and isinstance(TYPE.OF, lltype.Ptr)
+    #                       and TYPE.OF.TO._gckind == 'gc')
+
+# ____________________________________________________________
 
 
 class TypeLayoutBuilder(object):
     can_add_new_types = True
 
     def __init__(self):
-        dummy = {"weakptrofs": -1,
-                 "ofstolength": -1}
-        self.type_info_list = [dummy]   # don't use typeid 0, helps debugging
+        self.type_info_list = [None]   # don't use typeid 0, helps debugging
         self.id_of_type = {}      # {LLTYPE: type_id}
         self.seen_roots = {}
         # the following are lists of addresses of gc pointers living inside the
@@ -20,6 +206,8 @@
         # dictionary address -> list of addresses
         self.additional_roots_sources = 0
         self.finalizer_funcptrs = {}
+        self.offsettable_cache = {}
+        self.next_typeid_cache = {}
 
     def get_type_id(self, TYPE):
         try:
@@ -27,60 +215,56 @@
         except KeyError:
             assert self.can_add_new_types
             assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray))
-            # Record the new type_id description as a small dict for now.
-            # The framework gc transformer will turn it into a
-            # Struct("type_info") in flatten_table().
-            type_id = len(self.type_info_list)
+            # Record the new type_id description as a TYPE_INFO structure.
+            # It goes into a list for now, which will be turned into a
+            # TYPE_INFO_TABLE in flatten_table() by the gc transformer.
+
+            # pick the next type_id with the correct bits set or cleared
+            mask, expected = get_typeid_bitmask(TYPE)
+            type_id = self.next_typeid_cache.get((mask, expected), 1)
+            while True:
+                if type_id == len(self.type_info_list):
+                    self.type_info_list.append(None)
+                if (self.type_info_list[type_id] is None and
+                    (type_id & mask) == expected):
+                    break         # can use this type_id
+                else:
+                    type_id += 1  # continue searching
+            self.next_typeid_cache[mask, expected] = type_id + 1
             assert type_id & 0xffff == type_id # make sure it fits into 2 bytes
-            info = {}
-            self.type_info_list.append(info)
+
+            # build the TYPE_INFO structure
+            info = lltype.malloc(GCData.TYPE_INFO, immortal=True, zero=True)
+            encode_type_shape(self, info, TYPE)
+            self.type_info_list[type_id] = info
             self.id_of_type[TYPE] = type_id
-            offsets = offsets_to_gc_pointers(TYPE)
-            info["ofstoptrs"] = self.offsets2table(offsets, TYPE)
-            info["finalizer"] = self.make_finalizer_funcptr_for_type(TYPE)
-            info["weakptrofs"] = weakpointer_offset(TYPE)
-            if not TYPE._is_varsize():
-                info["isvarsize"] = False
-                info["gcptrinvarsize"] = False
-                info["fixedsize"] = llarena.round_up_for_allocation(
-                    llmemory.sizeof(TYPE))
-                info["ofstolength"] = -1
-                # note about round_up_for_allocation(): in the 'info' table
-                # we put a rounded-up size only for fixed-size objects.  For
-                # varsize ones, the GC must anyway compute the size at run-time
-                # and round up that result.
-            else:
-                info["isvarsize"] = True
-                info["fixedsize"] = llmemory.sizeof(TYPE, 0)
-                if isinstance(TYPE, lltype.Struct):
-                    ARRAY = TYPE._flds[TYPE._arrayfld]
-                    ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
-                    info["ofstolength"] = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
-                    if ARRAY.OF != lltype.Void:
-                        info["ofstovar"] = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
-                    else:
-                        info["fixedsize"] = ofs1 + llmemory.sizeof(lltype.Signed)
-                    if ARRAY._hints.get('isrpystring'):
-                        info["fixedsize"] = llmemory.sizeof(TYPE, 1)
-                else:
-                    ARRAY = TYPE
-                    info["ofstolength"] = llmemory.ArrayLengthOffset(ARRAY)
-                    if ARRAY.OF != lltype.Void:
-                        info["ofstovar"] = llmemory.itemoffsetof(TYPE, 0)
-                    else:
-                        info["fixedsize"] = llmemory.ArrayLengthOffset(ARRAY) + llmemory.sizeof(lltype.Signed)
-                assert isinstance(ARRAY, lltype.Array)
-                if ARRAY.OF != lltype.Void:
-                    offsets = offsets_to_gc_pointers(ARRAY.OF)
-                else:
-                    offsets = ()
-                info["varofstoptrs"] = self.offsets2table(offsets, ARRAY.OF)
-                info["varitemsize"] = llmemory.sizeof(ARRAY.OF)
-                info["gcptrinvarsize"] = len(offsets) > 0
             return type_id
 
     def offsets2table(self, offsets, TYPE):
-        return offsets
+        try:
+            return self.offsettable_cache[TYPE]
+        except KeyError:
+            cachedarray = lltype.malloc(GCData.OFFSETS_TO_GC_PTR,
+                                        len(offsets), immortal=True)
+            for i, value in enumerate(offsets):
+                cachedarray[i] = value
+            self.offsettable_cache[TYPE] = cachedarray
+            return cachedarray
+
+    def flatten_table(self):
+        self.can_add_new_types = False
+        self.offsettable_cache = None
+        table = lltype.malloc(GCData.TYPE_INFO_TABLE, len(self.type_info_list),
+                              immortal=True)
+        fieldnames = GCData.TYPE_INFO._names
+        for tableentry, newcontent in zip(table, self.type_info_list):
+            if newcontent is None:    # empty entry
+                tableentry.weakptrofs = -1
+                tableentry.ofstolength = -1
+            else:
+                for name in fieldnames:
+                    setattr(tableentry, name, getattr(newcontent, name))
+        return table
 
     def finalizer_funcptr_for_type(self, TYPE):
         if TYPE in self.finalizer_funcptrs:
@@ -92,57 +276,8 @@
     def make_finalizer_funcptr_for_type(self, TYPE):
         return None   # must be overridden for proper finalizer support
 
-    def q_is_varsize(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["isvarsize"]
-
-    def q_has_gcptr_in_varsize(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["gcptrinvarsize"]
-
-    def q_finalizer(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["finalizer"]
-
-    def q_offsets_to_gc_pointers(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["ofstoptrs"]
-
-    def q_fixed_size(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["fixedsize"]
-
-    def q_varsize_item_sizes(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["varitemsize"]
-
-    def q_varsize_offset_to_variable_part(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["ofstovar"]
-
-    def q_varsize_offset_to_length(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["ofstolength"]
-
-    def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["varofstoptrs"]
-
-    def q_weakpointer_offset(self, typeid):
-        assert typeid > 0
-        return self.type_info_list[typeid]["weakptrofs"]
-
-    def get_query_functions(self):
-        return (self.q_is_varsize,
-                self.q_has_gcptr_in_varsize,
-                self.q_finalizer,
-                self.q_offsets_to_gc_pointers,
-                self.q_fixed_size,
-                self.q_varsize_item_sizes,
-                self.q_varsize_offset_to_variable_part,
-                self.q_varsize_offset_to_length,
-                self.q_varsize_offsets_to_gcpointers_in_var_part,
-                self.q_weakpointer_offset)
+    def initialize_gc_query_function(self, gc):
+        return GCData(self.type_info_list).set_query_functions(gc)
 
     def consider_constant(self, TYPE, value, gc):
         if value is not lltype.top_container(value):

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/memory/gcwrapper.py	Sat Dec 15 13:57:29 2007
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llheap
 from pypy.rpython import llinterp
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.memory.support import get_address_linked_list
 from pypy.rpython.memory import gctypelayout
 from pypy.objspace.flow.model import Constant
@@ -21,7 +22,7 @@
     def prepare_graphs(self, flowgraphs):
         layoutbuilder = DirectRunLayoutBuilder(self.llinterp)
         self.get_type_id = layoutbuilder.get_type_id
-        self.gc.set_query_functions(*layoutbuilder.get_query_functions())
+        layoutbuilder.initialize_gc_query_function(self.gc)
 
         constants = collect_constants(flowgraphs)
         for obj in constants:
@@ -144,7 +145,7 @@
             DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
             destrgraph = destrptr._obj.graph
         else:
-            return None
+            return lltype.nullptr(gctypelayout.GCData.FINALIZERTYPE.TO)
 
         assert not type_contains_pyobjs(TYPE), "not implemented"
         def ll_finalizer(addr):
@@ -154,7 +155,7 @@
             except llinterp.LLException:
                 raise RuntimeError(
                     "a finalizer raised an exception, shouldn't happen")
-        return ll_finalizer
+        return llhelper(gctypelayout.GCData.FINALIZERTYPE, ll_finalizer)
 
 
 def collect_constants(graphs):

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/ootype.py	Sat Dec 15 13:57:29 2007
@@ -263,11 +263,12 @@
     # We try to keep Record as similar to Instance as possible, so backends
     # can treat them polymorphically, if they choose to do so.
     
-    def __init__(self, fields):
+    def __init__(self, fields, _hints={}):
         self._fields = frozendict()
         for name, ITEMTYPE in fields.items():
             self._fields[name] = ITEMTYPE, ITEMTYPE._defl()
         self._null = _null_record(self)
+        self._hints = frozendict(_hints)
 
     def _defl(self):
         return self._null

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/rbuiltin.py	Sat Dec 15 13:57:29 2007
@@ -40,6 +40,18 @@
     return hop.genop('ooidentityhash', vlist,
                      resulttype = ootype.Signed)
 
+def rtype_ooupcast(hop):
+    assert isinstance(hop.args_s[0].const, ootype.Instance)
+    assert isinstance(hop.args_s[1], annmodel.SomeOOInstance)
+    v_inst = hop.inputarg(hop.args_r[1], arg=1)
+    return hop.genop('ooupcast', [v_inst], resulttype = hop.r_result.lowleveltype)
+
+def rtype_oodowncast(hop):
+    assert isinstance(hop.args_s[0].const, ootype.Instance)
+    assert isinstance(hop.args_s[1], annmodel.SomeOOInstance)
+    v_inst = hop.inputarg(hop.args_r[1], arg=1)
+    return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype)
+
 def rtype_builtin_isinstance(hop):
     if hop.s_result.is_constant():
         return hop.inputconst(ootype.Bool, hop.s_result.const)
@@ -98,6 +110,8 @@
 BUILTIN_TYPER[ootype.subclassof] = rtype_subclassof
 BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
 BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
+BUILTIN_TYPER[ootype.ooupcast] = rtype_ooupcast
+BUILTIN_TYPER[ootype.oodowncast] = rtype_oodowncast
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
 BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
 BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/ootypesystem/test/test_oortype.py	Sat Dec 15 13:57:29 2007
@@ -9,6 +9,7 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rlib.objectmodel import r_dict
+from pypy.tool.error import AnnotatorError
 from pypy.rpython.ootypesystem import ooregistry # side effects
 
 def gengraph(f, args=[], viewBefore=False, viewAfter=False, mangle=True):
@@ -300,3 +301,40 @@
     
     res = interpret(oof, [], type_system='ootype')
     assert res == 42
+
+def test_ooupcast():
+    A = Instance('A', ootype.ROOT, {})
+    B = Instance('B', A, {})
+    C = Instance('C', ootype.ROOT)
+
+    def fn():
+        b = new(B)
+        return ooupcast(A, b)
+
+    res = interpret(fn, [], type_system='ootype')
+    assert typeOf(res) is A
+
+    def fn():
+        c = new(C)
+        return ooupcast(A, c)
+
+    py.test.raises(AnnotatorError, interpret, fn, [], type_system='ootype')
+
+def test_oodowncast():
+    A = Instance('A', ootype.ROOT, {})
+    B = Instance('B', A, {})
+    C = Instance('C', ootype.ROOT)
+
+    def fn():
+        b = new(B)
+        a = ooupcast(A, b)
+        return oodowncast(B, a)
+
+    res = interpret(fn, [], type_system='ootype')
+    assert typeOf(res) is B
+
+    def fn():
+        c = new(C)
+        return oodowncast(A, c)
+
+    py.test.raises(AnnotatorError, interpret, fn, [], type_system='ootype')

Modified: pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/rpython/rpbc.py	Sat Dec 15 13:57:29 2007
@@ -666,7 +666,7 @@
         if desc not in self.s_pbc.descriptions:
             raise TyperError("%r not in %r" % (cls, self))
         if self.lowleveltype is Void:
-            return desc.pyobj
+            return None
         return rclass.get_type_repr(self.rtyper).convert_desc(desc)
 
     def convert_const(self, cls):

Modified: pypy/branch/lazy-write-barrier/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/c/database.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/c/database.py	Sat Dec 15 13:57:29 2007
@@ -164,9 +164,9 @@
             self.containerstats[kind] = self.containerstats.get(kind, 0) + 1
             self.containerlist.append(node)
             if self.completed:
-                assert not node.globalcontainer
-                # non-global containers are found very late, e.g. _subarrays
-                # via addresses introduced by the GC transformer
+                pass # we would like to fail here, but a few containers
+                     # are found very late, e.g. _subarrays via addresses
+                     # introduced by the GC transformer, or the type_info_table
         return node
 
     def get(self, obj):
@@ -195,11 +195,15 @@
                         n = len('delayed!')
                         if len(name) == n:
                             raise
-                        if id(obj) in self.delayedfunctionnames:
-                            return self.delayedfunctionnames[id(obj)][0]
-                        funcname = name[n:]
-                        funcname = self.namespace.uniquename('g_' + funcname)
-                        self.delayedfunctionnames[id(obj)] = funcname, obj
+                        if isinstance(lltype.typeOf(obj).TO, lltype.FuncType):
+                            if id(obj) in self.delayedfunctionnames:
+                                return self.delayedfunctionnames[id(obj)][0]
+                            funcname = name[n:]
+                            funcname = self.namespace.uniquename('g_'+funcname)
+                            self.delayedfunctionnames[id(obj)] = funcname, obj
+                        else:
+                            funcname = None      # can't use the name of a
+                                                 # delayed non-function ptr
                         self.delayedfunctionptrs.append(obj)
                         return funcname
                         # /hack hack hack

Modified: pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/c/test/test_boehm.py	Sat Dec 15 13:57:29 2007
@@ -98,8 +98,9 @@
         assert 0 < res <= 84
 
     def test_id_is_weak(self):
-        # test that id(obj) does not keep obj alive
+        # test that compute_unique_id(obj) does not keep obj alive
         from pypy.rpython.lltypesystem.lloperation import llop
+        from pypy.rlib.objectmodel import compute_unique_id
         class State:
             pass
         s = State()
@@ -113,11 +114,11 @@
             pass
         def run_once():
             a = A()
-            ida = id(a)
+            ida = compute_unique_id(a)
             b = B()
-            idb = id(b)
+            idb = compute_unique_id(b)
             c = C()
-            idc = id(c)
+            idc = compute_unique_id(c)
             llop.gc__collect(lltype.Void)
             llop.gc__collect(lltype.Void)
             llop.gc__collect(lltype.Void)

Modified: pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/cli/dotnet.py	Sat Dec 15 13:57:29 2007
@@ -402,11 +402,13 @@
             return OverloadingResolver.lltype_to_annotation(TYPE)
 
     def specialize_call(self, hop):
-        v_obj, v_type = hop.inputargs(*hop.args_r)
-        if v_type.value is ootype.String or isinstance(v_type.value, (type, types.ClassType)):
+        TYPE = hop.args_v[1].value
+        v_obj = hop.inputarg(hop.args_r[0], arg=0)
+        if TYPE is ootype.String or isinstance(TYPE, (type, types.ClassType)):
             return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype)
         else:
-            return hop.genop('cliunbox', [v_obj, v_type], hop.r_result.lowleveltype)
+            c_type = hop.inputconst(ootype.Void, TYPE)
+            return hop.genop('cliunbox', [v_obj, c_type], hop.r_result.lowleveltype)
 
 
 native_exc_cache = {}

Modified: pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py
==============================================================================
--- pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py	(original)
+++ pypy/branch/lazy-write-barrier/pypy/translator/goal/bench-cronjob.py	Sat Dec 15 13:57:29 2007
@@ -182,10 +182,8 @@
         backends = [backend.strip() for backend in """
             c
             c--stackless--_faassen
-            c--_faassen
+            c--_faassen--_allworkingmodules
             c--thread
-            c--_objspace=taint
-            c--_allworkingmodules
             c--gc=marksweep--_faassen
             c--gc=semispace--_faassen
             c--gc=generation--_faassen



More information about the Pypy-commit mailing list