[pypy-svn] r31568 - in pypy/dist/pypy: annotation jit/codegen/i386 jit/codegen/i386/test jit/codegen/llgraph jit/llabstractinterp jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem rpython/test

arigo at codespeak.net arigo at codespeak.net
Wed Aug 23 18:47:41 CEST 2006


Author: arigo
Date: Wed Aug 23 18:47:27 2006
New Revision: 31568

Removed:
   pypy/dist/pypy/rpython/rgenop.py
   pypy/dist/pypy/rpython/test/test_rgenop.py
Modified:
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/policy.py
   pypy/dist/pypy/jit/codegen/i386/ri386genop.py
   pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py
   pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
   pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
   pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py
   pypy/dist/pypy/jit/llabstractinterp/llcontainer.py
   pypy/dist/pypy/jit/llabstractinterp/llvalue.py
   pypy/dist/pypy/jit/timeshifter/oop.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/rvalue.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/test/test_tl.py
   pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
   pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
   pypy/dist/pypy/jit/timeshifter/timeshift.py
   pypy/dist/pypy/jit/timeshifter/vlist.py
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/lltypesystem/rlist.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rpbc.py
Log:
(pedronis, arigo)

Make the timeshifter parametrized on a RGenOp class, which is the
interface to specific code generation back-ends.  For this we did the
following:

    slightly change the interface of rgenop, which is now located in
    pypy/jit/codegen/*/rgenop.py and is based on classes a bit more.

    the old rgenop with opaque objects is located in codegen/llgraph/llimpl
    and codegen/llgraph/rgenop gives a nicer OO interface over it.

    updated codegen/i386/ri386genop to match the same OO interface.

    fixed everything everywhere.

    _annspecialcase_ = 'specialize:ll' can be used with any policy now.

    added lltypesystem.rclass.fishllattr() to read an instance attribute
    when we only have a low-level GcStruct.  (Could be used to replace a few
    existing 'inst_xyz' attribute fishing, too.)



Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Wed Aug 23 18:47:27 2006
@@ -408,18 +408,16 @@
                     result.knowntype = tp # at least for types this needs to be correct
                 else:
                     result = SomePBC([self.getdesc(x)])
-        elif hasattr(x, '__class__') \
-                 and x.__class__.__module__ != '__builtin__':
+        elif hasattr(x, '_freeze_') and x._freeze_():
             # user-defined classes can define a method _freeze_(), which
             # is called when a prebuilt instance is found.  If the method
             # returns True, the instance is considered immutable and becomes
             # a SomePBC().  Otherwise it's just SomeInstance().
-            frozen = hasattr(x, '_freeze_') and x._freeze_()
-            if frozen:
-                result = SomePBC([self.getdesc(x)])
-            else:
-                self.see_mutable(x)
-                result = SomeInstance(self.getuniqueclassdef(x.__class__))
+            result = SomePBC([self.getdesc(x)])
+        elif hasattr(x, '__class__') \
+                 and x.__class__.__module__ != '__builtin__':
+            self.see_mutable(x)
+            result = SomeInstance(self.getuniqueclassdef(x.__class__))
         elif x is None:
             return s_None
         else:
@@ -512,18 +510,16 @@
                     result.knowntype = tp # at least for types this needs to be correct
                 else:
                     result = SomePBC([self.getdesc(x)])
-        elif hasattr(x, '__class__') \
-                 and x.__class__.__module__ != '__builtin__':
+        elif hasattr(x, '_freeze_') and x._freeze_():
             # user-defined classes can define a method _freeze_(), which
             # is called when a prebuilt instance is found.  If the method
             # returns True, the instance is considered immutable and becomes
             # a SomePBC().  Otherwise it's just SomeInstance().
-            frozen = hasattr(x, '_freeze_') and x._freeze_()
-            if frozen:
-                result = SomePBC([self.getdesc(x)])
-            else:
-                self.see_mutable(x)
-                result = SomeInstance(self.getuniqueclassdef(x.__class__))
+            result = SomePBC([self.getdesc(x)])
+        elif hasattr(x, '__class__') \
+                 and x.__class__.__module__ != '__builtin__':
+            self.see_mutable(x)
+            result = SomeInstance(self.getuniqueclassdef(x.__class__))
         elif x is None:
             return s_None
         else:

Modified: pypy/dist/pypy/annotation/policy.py
==============================================================================
--- pypy/dist/pypy/annotation/policy.py	(original)
+++ pypy/dist/pypy/annotation/policy.py	Wed Aug 23 18:47:27 2006
@@ -8,7 +8,7 @@
 from pypy.annotation.bookkeeper import getbookkeeper
 
 
-class BasicAnnotatorPolicy:
+class BasicAnnotatorPolicy(object):
     allow_someobjects = True
 
     def event(pol, bookkeeper, what, *args):
@@ -83,6 +83,10 @@
     specialize__argtype = staticmethod(specialize_argtype) # specialize:argtype(N)
     specialize__arglistitemtype = staticmethod(specialize_arglistitemtype)
 
+    def specialize__ll(pol, *args):
+        from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
+        return LowLevelAnnotatorPolicy.default_specialize(*args)
+
     def override__ignore(pol, *args):
         bk = getbookkeeper()
         return bk.immutablevalue(None)

Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386genop.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py	Wed Aug 23 18:47:27 2006
@@ -1,16 +1,14 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.codegen.i386.codebuf import MachineCodeBlock
 from pypy.jit.codegen.i386.ri386 import *
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
+from pypy.jit.codegen.model import GenVar, GenConst
 
 
 WORD = 4
 
 
-class VarOrConst(object):
-    pass
-
-
-class Var(VarOrConst):
+class Var(GenVar):
 
     def __init__(self, stackpos):
         # 'stackpos' is an index relative to the pushed arguments:
@@ -28,13 +26,13 @@
         return block.stack_access(self.stackpos)
 
 
-class TypeConst(VarOrConst):
+class TypeConst(GenConst):
 
     def __init__(self, kind):
         self.kind = kind
 
 
-class IntConst(VarOrConst):
+class IntConst(GenConst):
 
     def __init__(self, value):
         self.value = value
@@ -42,6 +40,10 @@
     def operand(self, block):
         return imm(self.value)
 
+    def revealconst(self, T):
+        return lltype.cast_int_to_ptr(T, self.value)
+    revealconst._annspecialcase_ = 'specialize:arg(1)'
+
 
 class FnPtrConst(IntConst):
     def __init__(self, value, mc):
@@ -49,8 +51,9 @@
         self.mc = mc    # to keep it alive
 
 
-class Block(object):
-    def __init__(self, mc):
+class Block(CodeGenBlock):
+    def __init__(self, rgenop, mc):
+        self.rgenop = rgenop
         self.argcount = 0
         self.stackdepth = 0
         self.mc = mc
@@ -62,6 +65,21 @@
         self.stackdepth += 1
         return res
 
+    def genop(self, opname, args_gv, gv_RESTYPE=None):
+        genmethod = getattr(self, 'op_' + opname)
+        return genmethod(args_gv, gv_RESTYPE)
+    genop._annspecialcase_ = 'specialize:arg(1)'
+
+    def close1(self):
+        return Link(self)
+
+    def close2(self, gv_condition):
+        false_block = self.rgenop.newblock()
+        false_block.stackdepth = self.stackdepth
+        self.mc.CMP(gv_condition.operand(self), imm8(0))
+        self.mc.JE(rel32(false_block.startaddr))
+        return Link(false_block), Link(self)
+
     def stack_access(self, stackpos):
         return mem(esp, WORD * (self.stackdepth-1 - stackpos))
 
@@ -89,51 +107,24 @@
         return self.push(eax)
 
 
-class RI386GenOp(object):
-    gv_IntWord = TypeConst('IntWord')
-    gv_Void = TypeConst('Void')
+class Link(CodeGenLink):
 
-    def __init__(self):
-        self.mcs = []   # machine code blocks where no-one is currently writing
-
-    def get_rgenop_for_testing():
-        return RI386GenOp()
-    get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
-
-    def open_mc(self):
-        if self.mcs:
-            # XXX think about inserting NOPS for alignment
-            return self.mcs.pop()
-        else:
-            return MachineCodeBlock(65536)   # XXX supposed infinite for now
-
-    def close_mc(self, mc):
-        self.mcs.append(mc)
-
-    def newblock(self):
-        return Block(self.open_mc())
+    def __init__(self, prevblock):
+        self.prevblock = prevblock
 
-    def closeblock1(self, block):
-        return block   # NB. links and blocks are the same for us
+    def closereturn(self, gv_result):
+        block = self.prevblock
+        block.mc.MOV(eax, gv_result.operand(block))
+        block.mc.ADD(esp, imm(WORD * block.stackdepth))
+        block.mc.RET()
+        block.rgenop.close_mc(block.mc)
 
-    def closeblock2(self, block, gv_condition):
-        false_block = self.newblock()
-        false_block.stackdepth = block.stackdepth
-        block.mc.CMP(gv_condition.operand(block), imm8(0))
-        block.mc.JE(rel32(false_block.startaddr))
-        return false_block, block
-
-    def closereturnlink(self, link, gv_result):
-        link.mc.MOV(eax, gv_result.operand(link))
-        link.mc.ADD(esp, imm(WORD * link.stackdepth))
-        link.mc.RET()
-        self.close_mc(link.mc)
-
-    def closelink(self, link, outputargs_gv, targetblock):
+    def close(self, outputargs_gv, targetblock):
+        block = self.prevblock
         N = len(outputargs_gv)
-        if link.stackdepth < N:
-            link.mc.SUB(esp, imm(WORD * (N - link.stackdepth)))
-            link.stackdepth = N
+        if block.stackdepth < N:
+            block.mc.SUB(esp, imm(WORD * (N - block.stackdepth)))
+            block.stackdepth = N
 
         pending_dests = N
         srccount = [0] * N
@@ -155,15 +146,15 @@
                     srccount[i] = -1
                     pending_dests -= 1
                     gv_src = outputargs_gv[i]
-                    link.mc.MOV(eax, gv_src.operand(link))
-                    link.mc.MOV(link.stack_access(i), eax)
+                    block.mc.MOV(eax, gv_src.operand(block))
+                    block.mc.MOV(block.stack_access(i), eax)
                     progress = True
             if not progress:
                 # we are left with only pure disjoint cycles; break them
                 for i in range(N):
                     if srccount[i] >= 0:
                         dst = i
-                        link.mc.MOV(edx, link.stack_access(dst))
+                        block.mc.MOV(edx, block.stack_access(dst))
                         while True:
                             assert srccount[dst] == 1
                             srccount[dst] = -1
@@ -174,20 +165,42 @@
                             assert 0 <= src < N
                             if src == i:
                                 break
-                            link.mc.MOV(eax, link.stack_access(src))
-                            link.mc.MOV(link.stack_access(dst), eax)
+                            block.mc.MOV(eax, block.stack_access(src))
+                            block.mc.MOV(block.stack_access(dst), eax)
                             dst = src
-                        link.mc.MOV(link.stack_access(dst), edx)
+                        block.mc.MOV(block.stack_access(dst), edx)
                 assert pending_dests == 0
 
-        if link.stackdepth > N:
-            link.mc.ADD(esp, imm(WORD * (link.stackdepth - N)))
-            link.stackdepth = N
-        link.mc.JMP(rel32(targetblock.startaddr))
-        self.close_mc(link.mc)
+        if block.stackdepth > N:
+            block.mc.ADD(esp, imm(WORD * (block.stackdepth - N)))
+            block.stackdepth = N
+        block.mc.JMP(rel32(targetblock.startaddr))
+        block.rgenop.close_mc(block.mc)
+
+
+class RI386GenOp(AbstractRGenOp):
+    gv_IntWord = TypeConst('IntWord')
+    gv_Void = TypeConst('Void')
+
+    def __init__(self):
+        self.mcs = []   # machine code blocks where no-one is currently writing
+
+    def get_rgenop_for_testing():
+        return RI386GenOp()
+    get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
+
+    def open_mc(self):
+        if self.mcs:
+            # XXX think about inserting NOPS for alignment
+            return self.mcs.pop()
+        else:
+            return MachineCodeBlock(65536)   # XXX supposed infinite for now
 
-    def geninputarg(self, block, gv_TYPE):
-        return block.geninputarg(gv_TYPE)
+    def close_mc(self, mc):
+        self.mcs.append(mc)
+
+    def newblock(self):
+        return Block(self, self.open_mc())
 
     def genconst(llvalue):
         T = lltype.typeOf(llvalue)
@@ -204,11 +217,6 @@
     constTYPE._annspecialcase_ = 'specialize:memo'
     constTYPE = staticmethod(constTYPE)
 
-    def genop(self, block, opname, args_gv, gv_RESTYPE):
-        genmethod = getattr(block, 'op_' + opname)
-        return genmethod(args_gv, gv_RESTYPE)
-    genop._annspecialcase_ = 'specialize:arg(2)'
-
     def gencallableconst(self, name, block, gv_FUNCTYPE):
         prologue = self.newblock()
         #prologue.mc.BREAKPOINT()
@@ -220,9 +228,3 @@
         prologue.mc.JMP(rel32(block.startaddr))
         self.close_mc(prologue.mc)
         return FnPtrConst(prologue.startaddr, prologue.mc)
-
-    def revealconst(T, gv_const):
-        assert isinstance(gv_const, IntConst)    # for now
-        return lltype.cast_int_to_ptr(T, gv_const.value)
-    revealconst._annspecialcase_ = 'specialize:arg(0)'
-    revealconst = staticmethod(revealconst)

Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py	Wed Aug 23 18:47:27 2006
@@ -14,12 +14,12 @@
     # 'return x+n'
     gv_SIGNED = rgenop.constTYPE(lltype.Signed)
     block = rgenop.newblock()
-    gv_x = rgenop.geninputarg(block, gv_SIGNED)
+    gv_x = block.geninputarg(gv_SIGNED)
     args_gv = [gv_x,
                rgenop.genconst(n)]
-    gv_result = rgenop.genop(block, "int_add", args_gv, gv_SIGNED)
-    link = rgenop.closeblock1(block)
-    rgenop.closereturnlink(link, gv_result)
+    gv_result = block.genop("int_add", args_gv, gv_SIGNED)
+    link = block.close1()
+    link.closereturn(gv_result)
 
     gv_FUNC = rgenop.constTYPE(FUNC)
     gv_add_one = rgenop.gencallableconst("adder", block, gv_FUNC)
@@ -28,15 +28,15 @@
 def runner(x, y):
     rgenop = RI386GenOp()
     gv_add_x = make_adder(rgenop, x)
-    add_x = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_x)
+    add_x = gv_add_x.revealconst(lltype.Ptr(FUNC))
     res = add_x(y)
     keepalive_until_here(rgenop)    # to keep the code blocks alive
     return res
 
 def test_adder_interpret():
-    from pypy.rpython import rgenop
+    from pypy.jit.codegen.llgraph.rgenop import rgenop
     gv_add_5 = make_adder(rgenop, 5)
-    add_5 = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_5)
+    add_5 = gv_add_5.revealconst(lltype.Ptr(FUNC))
     llinterp = LLInterpreter(None)
     res = llinterp.eval_graph(add_5._obj.graph, [12])
     assert res == 17
@@ -62,25 +62,25 @@
     # 'return x - (y - (x-1))'
     gv_SIGNED = rgenop.constTYPE(lltype.Signed)
     block = rgenop.newblock()
-    gv_x = rgenop.geninputarg(block, gv_SIGNED)
-    gv_y = rgenop.geninputarg(block, gv_SIGNED)
+    gv_x = block.geninputarg(gv_SIGNED)
+    gv_y = block.geninputarg(gv_SIGNED)
     args_gv = [gv_x, rgenop.genconst(1)]
-    gv_z = rgenop.genop(block, "int_sub", args_gv, gv_SIGNED)
-    link = rgenop.closeblock1(block)
+    gv_z = block.genop("int_sub", args_gv, gv_SIGNED)
+    link = block.close1()
 
     block2 = rgenop.newblock()
-    gv_y2 = rgenop.geninputarg(block2, gv_SIGNED)
-    gv_z2 = rgenop.geninputarg(block2, gv_SIGNED)
-    gv_x2 = rgenop.geninputarg(block2, gv_SIGNED)
-    rgenop.closelink(link, [gv_y, gv_z, gv_x], block2)
+    gv_y2 = block2.geninputarg(gv_SIGNED)
+    gv_z2 = block2.geninputarg(gv_SIGNED)
+    gv_x2 = block2.geninputarg(gv_SIGNED)
+    link.close([gv_y, gv_z, gv_x], block2)
 
     args_gv = [gv_y2, gv_z2]
-    gv_s2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
+    gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
     args_gv = [gv_x2, gv_s2]
-    gv_t2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
-    link2 = rgenop.closeblock1(block2)
+    gv_t2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+    link2 = block2.close1()
 
-    rgenop.closereturnlink(link2, gv_t2)
+    link2.closereturn(gv_t2)
     gv_FUNC2 = rgenop.constTYPE(FUNC2)
     gv_dummyfn = rgenop.gencallableconst("dummy", block, gv_FUNC2)
     return gv_dummyfn
@@ -88,15 +88,15 @@
 def dummy_runner(x, y):
     rgenop = RI386GenOp()
     gv_dummyfn = make_dummy(rgenop)
-    dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+    dummyfn = gv_dummyfn.revealconst(lltype.Ptr(FUNC2))
     res = dummyfn(x, y)
     keepalive_until_here(rgenop)    # to keep the code blocks alive
     return res
 
 def test_dummy_interpret():
-    from pypy.rpython import rgenop
+    from pypy.jit.codegen.llgraph.rgenop import rgenop
     gv_dummyfn = make_dummy(rgenop)
-    dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+    dummyfn = gv_dummyfn.revealconst(lltype.Ptr(FUNC2))
     llinterp = LLInterpreter(None)
     res = llinterp.eval_graph(dummyfn._obj.graph, [30, 17])
     assert res == 42
@@ -122,22 +122,22 @@
     gv_SIGNED = rgenop.constTYPE(lltype.Signed)
     gv_BOOL   = rgenop.constTYPE(lltype.Bool)
     block = rgenop.newblock()
-    gv_x = rgenop.geninputarg(block, gv_SIGNED)
-    gv_y = rgenop.geninputarg(block, gv_SIGNED)
+    gv_x = block.geninputarg(gv_SIGNED)
+    gv_y = block.geninputarg(gv_SIGNED)
     args_gv = [gv_x, rgenop.genconst(5)]
-    gv_cond = rgenop.genop(block, "int_gt", args_gv, gv_BOOL)
-    link_false, link_true = rgenop.closeblock2(block, gv_cond)
+    gv_cond = block.genop("int_gt", args_gv, gv_BOOL)
+    link_false, link_true = block.close2(gv_cond)
 
     block2 = rgenop.newblock()
-    gv_x2 = rgenop.geninputarg(block2, gv_SIGNED)
-    rgenop.closelink(link_true, [gv_x], block2)
+    gv_x2 = block2.geninputarg(gv_SIGNED)
+    link_true.close([gv_x], block2)
 
     args_gv = [gv_x2, rgenop.genconst(1)]
-    gv_s2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
-    link2 = rgenop.closeblock1(block2)
-    rgenop.closereturnlink(link2, gv_s2)
+    gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+    link2 = block2.close1()
+    link2.closereturn(gv_s2)
 
-    rgenop.closereturnlink(link_false, gv_y)
+    link_false.closereturn(gv_y)
 
     gv_FUNC2 = rgenop.constTYPE(FUNC2)
     gv_branchingfn = rgenop.gencallableconst("branching", block, gv_FUNC2)
@@ -146,15 +146,15 @@
 def branching_runner(x, y):
     rgenop = RI386GenOp()
     gv_branchingfn = make_branching(rgenop)
-    branchingfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_branchingfn)
+    branchingfn = gv_branchingfn.revealconst(lltype.Ptr(FUNC2))
     res = branchingfn(x, y)
     keepalive_until_here(rgenop)    # to keep the code blocks alive
     return res
 
 def test_branching_interpret():
-    from pypy.rpython import rgenop
+    from pypy.jit.codegen.llgraph.rgenop import rgenop
     gv_branchingfn = make_branching(rgenop)
-    branchingfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_branchingfn)
+    branchingfn = gv_branchingfn.revealconst(lltype.Ptr(FUNC2))
     llinterp = LLInterpreter(None)
     res = llinterp.eval_graph(branchingfn._obj.graph, [30, 17])
     assert res == 29

Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py	Wed Aug 23 18:47:27 2006
@@ -12,6 +12,7 @@
 from pypy.rpython.module.support import LLSupport
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.lltypesystem.rclass import fishllattr
 
 
 # for debugging, sanity checks in non-RPython code
@@ -42,13 +43,13 @@
 def _inputvars(vars):
     if not isinstance(vars, list):
         n = vars.ll_length()
-        vars = [getattr(llvar, 'inst_v', llvar) for llvar in vars.ll_items()]
+        vars = vars.ll_items()
+        vars = [fishllattr(vars[i], 'v', vars[i]) for i in range(n)]
     else:
-        n = len(vars)
         vars = [getattr(llvar, 'v', llvar) for llvar in vars]
     res = []
-    for i in range(n):
-        v = from_opaque_object(vars[i])
+    for v1 in vars:
+        v = from_opaque_object(v1)
         assert isinstance(v, (flowmodel.Constant, flowmodel.Variable))
         res.append(v)
     return res

Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	Wed Aug 23 18:47:27 2006
@@ -1,7 +1,8 @@
 from pypy.rpython.lltypesystem import lltype
-from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
 from pypy.jit.codegen.model import GenVar, GenConst
 from pypy.jit.codegen.llgraph import llimpl
+from pypy.rpython.lltypesystem.rclass import fishllattr
 
 
 class LLVar(GenVar):
@@ -18,6 +19,9 @@
     revealconst._annspecialcase_ = 'specialize:arg(1)'
 
 
+gv_Void = LLConst(llimpl.constTYPE(lltype.Void))
+
+
 class LLBlock(CodeGenBlock):
     def __init__(self, b):
         self.b = b
@@ -25,8 +29,9 @@
     def geninputarg(self, gv_TYPE):
         return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v))
 
-    def genop(self, opname, vars_gv, gv_RESULT_TYPE):
-        return LLVar(llimpl.genop(self.b, opname, vars_gv, gv_RESULT_TYPE.v))
+    def genop(self, opname, vars_gv, gv_RESULT_TYPE=None):
+        return LLVar(llimpl.genop(self.b, opname, vars_gv,
+                                  (gv_RESULT_TYPE or gv_Void).v))
     genop._annspecialcase_ = 'specialize:arg(1)'
 
     def close1(self):
@@ -49,6 +54,7 @@
 
 
 class RGenOp(AbstractRGenOp):
+    gv_Void = gv_Void
 
     def newblock(self):
         return LLBlock(llimpl.newblock())
@@ -68,7 +74,7 @@
     constTYPE = staticmethod(constTYPE)
 
     def placeholder(dummy):
-        return LLConst(llimpl.placerholder(dummy))
+        return LLConst(llimpl.placeholder(dummy))
     placeholder._annspecialcase_ = 'specialize:arg(0)'
     placeholder = staticmethod(placeholder)
 
@@ -76,3 +82,31 @@
         return LLConst(llimpl.constFieldName(name))
     constFieldName._annspecialcase_ = 'specialize:memo'
     constFieldName = staticmethod(constFieldName)
+
+    constPrebuiltGlobal = genconst
+
+    # not RPython, just for debugging.  Specific to llgraph.
+    def reveal(gv):
+        return llimpl.reveal(gv.v)
+    reveal = staticmethod(reveal)
+
+    # Builds a real flow.model.FunctionGraph. Specific to llgraph.
+    def buildgraph(block):
+        if hasattr(block, 'b'):
+            b = block.b
+        else:
+            b = fishllattr(block, 'b')
+        return llimpl.buildgraph(b)
+    buildgraph = staticmethod(buildgraph)
+
+    testgengraph = staticmethod(llimpl.testgengraph)
+
+    def get_rgenop_for_testing():
+        return rgenop
+    get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
+
+    def _freeze_(self):
+        return True    # no real point in using a full class in llgraph
+
+
+rgenop = RGenOp()      # no real point in using a full class in llgraph

Modified: pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py	Wed Aug 23 18:47:27 2006
@@ -10,7 +10,7 @@
 from pypy.jit.llabstractinterp.llcontainer import LLAbstractContainer
 from pypy.jit.llabstractinterp.llcontainer import virtualcontainervalue
 from pypy.jit.llabstractinterp.llcontainer import hasllcontent
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
 
 # ____________________________________________________________
 
@@ -264,7 +264,7 @@
         self.target_set = False
 
     def setreturn(self):
-        rgenop.closereturnlink(self.link, self.args_genv[0])
+        self.link.closereturn(self.args_genv[0])
         self.target_set = True
 
     def settarget(self, block, blockargs):
@@ -277,7 +277,7 @@
                 assert v1.value == v2.value
             else:
                 args.append(v1)
-        rgenop.closelink(self.link, args, block)
+        self.link.close(args, block)
         self.target_set = True
 
 class GraphState(object):
@@ -524,14 +524,14 @@
     def buildblock(self, newexitswitch, newlinkstates):
         b = self.newblock
         if newexitswitch is None:
-            link = rgenop.closeblock1(b)
+            link = b.close1()
             newlinkstates[0].link = link
             return b
 
         assert len(newlinkstates) == 2
 
         v = newexitswitch.getgenvar(self)
-        false_link, true_link = rgenop.closeblock2(b, v)
+        false_link, true_link = b.close2(v)
         
         cases = {False: false_link, True: true_link}
         for ls in newlinkstates:
@@ -539,14 +539,17 @@
         return b
 
     def genop(self, opname, args, RESULT_TYPE=lltype.Void):
-        return rgenop.genop(self.newblock, opname, args,
-                            rgenop.constTYPE(RESULT_TYPE))
+        return self.newblock.genop(opname, args,
+                                   rgenop.constTYPE(RESULT_TYPE))
 
     def genconst(self, llvalue):
         return rgenop.genconst(llvalue)
 
     def genvoidconst(self, placeholder):
         return rgenop.placeholder(placeholder)
+
+    def constTYPE(self, T):
+        return T
     
     def binding(self, v):
         assert isinstance(v, (Constant, Variable))

Modified: pypy/dist/pypy/jit/llabstractinterp/llcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llcontainer.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llcontainer.py	Wed Aug 23 18:47:27 2006
@@ -1,6 +1,6 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.llabstractinterp.llvalue import LLAbstractValue, AConstant, const
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
 
 class LLAbstractContainer(object):
     """Abstract base class for abstract containers.
@@ -51,7 +51,8 @@
     def build_runtime_container(self, builder):
         RESULT_TYPE = lltype.Ptr(self.T)
         if self.a_parent is not None:
-            parentindex = rgenop.constFieldName(self.parentindex)
+            PARENT_TYPE = self.a_parent.getconcretetype().TO
+            parentindex = rgenop.constFieldName(PARENT_TYPE, self.parentindex)
             v_parent = self.a_parent.forcegenvarorconst(builder)
             v_result = builder.genop('getsubstruct',
                                      [v_parent, parentindex], RESULT_TYPE)
@@ -75,8 +76,9 @@
                 T = self.fieldtype(name)
                 if isinstance(T, lltype.ContainerType):
                     # initialize the substructure/subarray
+                    c_name = rgenop.constFieldName(self.T, name)
                     v_subptr = builder.genop('getsubstruct',
-                                             [v_target, rgenop.constFieldName(name)],
+                                             [v_target, c_name],
                                              lltype.Ptr(T))
                     assert isinstance(a_value.content, LLVirtualContainer)
                     a_value.content.buildcontent(builder, v_subptr)
@@ -165,7 +167,8 @@
         return getattr(self.T, name)
 
     def setop(self, builder, v_target, name, v_value):
-        builder.genop('setfield', [v_target, rgenop.constFieldName(name), v_value],
+        c_name = rgenop.constFieldName(self.T, name)
+        builder.genop('setfield', [v_target, c_name, v_value],
                       lltype.Void)
 
 

Modified: pypy/dist/pypy/jit/llabstractinterp/llvalue.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llvalue.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llvalue.py	Wed Aug 23 18:47:27 2006
@@ -1,6 +1,6 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
 from pypy.tool.uid import Hashable
 
 class AVariable(object):
@@ -202,7 +202,7 @@
             assert c.concretetype == self.concretetype
             result = LLAbstractValue(c)
         else:
-            gen_v = rgenop.geninputarg(block, rgenop.constTYPE(self.concretetype))
+            gen_v = block.geninputarg(rgenop.constTYPE(self.concretetype))
             result = LLAbstractValue(AVariable(self.concretetype, genvar=gen_v))
         result.origin.append(self)
         return result

Modified: pypy/dist/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/oop.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/oop.py	Wed Aug 23 18:47:27 2006
@@ -1,5 +1,4 @@
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
 from pypy.jit.timeshifter.rcontainer import cachedtype
 from pypy.jit.timeshifter import rvalue
 
@@ -12,7 +11,7 @@
 class OopSpecDesc:
     __metaclass__ = cachedtype
 
-    def __init__(self, fnobj):
+    def __init__(self, RGenOp, fnobj):
         ll_func = fnobj._callable
         FUNCTYPE = lltype.typeOf(fnobj)
         nb_args = len(FUNCTYPE.ARGS)
@@ -37,14 +36,14 @@
             ARGTYPE = FUNCTYPE.ARGS[i]
             assert ((i+1) in self.argpositions) == (ARGTYPE is not lltype.Void)
 
-        self.args_gv = [rgenop.placeholder(None)] * nb_args
-        self.args_gv.insert(0, rgenop.genconst(fnobj._as_ptr()))
-        self.gv_result_type = rgenop.constTYPE(FUNCTYPE.RESULT)
+        self.args_gv = [RGenOp.placeholder(None)] * nb_args
+        self.args_gv.insert(0, RGenOp.constPrebuiltGlobal(fnobj._as_ptr()))
+        self.gv_result_type = RGenOp.constTYPE(FUNCTYPE.RESULT)
         self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
 
         if operation_name == 'newlist':
             from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist
-            self.typedesc = ListTypeDesc(FUNCTYPE.RESULT.TO)
+            self.typedesc = ListTypeDesc(RGenOp, FUNCTYPE.RESULT.TO)
             self.ll_handler = oop_newlist
         else:
             typename, method = operation_name.split('.')

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Wed Aug 23 18:47:27 2006
@@ -1,6 +1,5 @@
 import operator
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
 from pypy.jit.timeshifter import rvalue
 
 class AbstractContainer(object):
@@ -30,28 +29,29 @@
     __metaclass__ = cachedtype
     firstsubstructdesc = None
 
-    def __init__(self, TYPE):
+    def __init__(self, RGenOp, TYPE):
         self.TYPE = TYPE
         self.PTRTYPE = lltype.Ptr(TYPE)
-        self.gv_type = rgenop.constTYPE(self.TYPE)
-        self.gv_ptrtype = rgenop.constTYPE(self.PTRTYPE)
+        self.gv_type = RGenOp.constTYPE(self.TYPE)
+        self.gv_ptrtype = RGenOp.constTYPE(self.PTRTYPE)
 
         fielddescs = []
         for name in self.TYPE._names:
             FIELDTYPE = getattr(self.TYPE, name)
             if isinstance(FIELDTYPE, lltype.ContainerType):
-                substructdesc = StructTypeDesc(FIELDTYPE)
+                substructdesc = StructTypeDesc(RGenOp, FIELDTYPE)
                 assert name == self.TYPE._names[0], (
                     "unsupported: inlined substructures not as first field")
                 self.firstsubstructdesc = substructdesc
                 for subfielddesc in substructdesc.fielddescs:
                     dottedname = '%s.%s' % (name, subfielddesc.fieldname)
                     index = len(fielddescs)
-                    fielddescs.append(StructFieldDesc(self.PTRTYPE, dottedname,
-                                                      index))
+                    fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE,
+                                                      dottedname, index))
             else:
                 index = len(fielddescs)
-                fielddescs.append(StructFieldDesc(self.PTRTYPE, name, index))
+                fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE,
+                                                  name, index))
         self.fielddescs = fielddescs
 
     def getfielddesc(self, name):
@@ -79,12 +79,12 @@
 class FieldDesc(object):
     __metaclass__ = cachedtype
 
-    def __init__(self, PTRTYPE, RESTYPE):
+    def __init__(self, RGenOp, PTRTYPE, RESTYPE):
         self.PTRTYPE = PTRTYPE
         if isinstance(RESTYPE, lltype.ContainerType):
             RESTYPE = lltype.Ptr(RESTYPE)
         self.RESTYPE = RESTYPE
-        self.gv_resulttype = rgenop.constTYPE(RESTYPE)
+        self.gv_resulttype = RGenOp.constTYPE(RESTYPE)
         self.redboxcls = rvalue.ll_redboxcls(RESTYPE)
         self.immutable = PTRTYPE.TO._hints.get('immutable', False)
 
@@ -93,8 +93,8 @@
 
 class NamedFieldDesc(FieldDesc):
 
-    def __init__(self, PTRTYPE, name):
-        FieldDesc.__init__(self, PTRTYPE, getattr(PTRTYPE.TO, name))
+    def __init__(self, RGenOp, PTRTYPE, name):
+        FieldDesc.__init__(self, RGenOp, PTRTYPE, getattr(PTRTYPE.TO, name))
         self.structdepth = 0
         T = self.PTRTYPE.TO
         while (T._names and
@@ -102,33 +102,35 @@
             self.structdepth += 1
             T = getattr(T, T._names[0])
         self.fieldname = name
-        self.gv_fieldname = rgenop.constFieldName(name)
+        self.gv_fieldname = RGenOp.constFieldName(T, name)
 
 class ArrayFieldDesc(FieldDesc):
-    def __init__(self, PTRTYPE):
+    def __init__(self, RGenOp, PTRTYPE):
         assert isinstance(PTRTYPE.TO, lltype.Array)
-        FieldDesc.__init__(self, PTRTYPE, PTRTYPE.TO.OF)
+        FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF)
 
 class StructFieldDesc(object):
     __metaclass__ = cachedtype
 
-    def __init__(self, PTRTYPE, fieldname, index):
+    def __init__(self, RGenOp, PTRTYPE, fieldname, index):
         assert isinstance(PTRTYPE.TO, lltype.Struct)
         RES1 = PTRTYPE.TO
         accessptrtype_gv = self.accessptrtype_gv = [] 
+        accessors = []
         for component in fieldname.split('.'):
             LASTSTRUCT = RES1
-            accessptrtype_gv.append(rgenop.constTYPE(lltype.Ptr(LASTSTRUCT)))
+            accessptrtype_gv.append(RGenOp.constTYPE(lltype.Ptr(LASTSTRUCT)))
+            accessors.append((RES1, component))
             RES1 = getattr(RES1, component)
         assert not isinstance(RES1, lltype.ContainerType)
         self.PTRTYPE = PTRTYPE
         self.RESTYPE = RES1
-        self.gv_resulttype = rgenop.constTYPE(RES1)
+        self.gv_resulttype = RGenOp.constTYPE(RES1)
         self.fieldname = fieldname
-        self.fieldname_gv = [rgenop.constFieldName(component)
-                             for component in fieldname.split('.')]
+        self.fieldname_gv = [RGenOp.constFieldName(T, component)
+                             for T, component in accessors]
         self.fieldindex = index
-        self.gv_default = rgenop.genconst(RES1._defl())
+        self.gv_default = RGenOp.constPrebuiltGlobal(RES1._defl())
         self.redboxcls = rvalue.ll_redboxcls(RES1)
         self.immutable = LASTSTRUCT._hints.get('immutable', False)
 
@@ -149,7 +151,7 @@
         op_args = [gv_sub,
                    self.fieldname_gv[-1],
                    box.getgenvar(builder)]
-        genop('setfield', op_args, rgenop.gv_Void)        
+        genop('setfield', op_args, builder.rgenop.gv_Void)        
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Wed Aug 23 18:47:27 2006
@@ -1,6 +1,5 @@
 import operator, weakref
 from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
-from pypy.rpython import rgenop
 from pypy.jit.timeshifter import rvalue
 
 FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
@@ -19,13 +18,14 @@
     def _freeze_(self):
         return True
 
-    def __init__(self, opname, ARGS, RESULT):
+    def __init__(self, RGenOp, opname, ARGS, RESULT):
+        self.RGenOp = RGenOp
         self.opname = opname
         self.llop = lloperation.LL_OPERATIONS[opname]
         self.nb_args = len(ARGS)
         self.ARGS = ARGS
         self.RESULT = RESULT
-        self.gv_RESULT = rgenop.constTYPE(RESULT)
+        self.gv_RESULT = RGenOp.constTYPE(RESULT)
         self.redboxcls = rvalue.ll_redboxcls(RESULT)
         self.canfold = opname in FOLDABLE_OPS
 
@@ -43,7 +43,7 @@
 
 def make_opdesc(hop):
     hrtyper = hop.rtyper
-    op_key = (hop.spaceop.opname,
+    op_key = (hrtyper.RGenOp, hop.spaceop.opname,
               tuple([hrtyper.originalconcretetype(s_arg) for s_arg in hop.args_s]),
               hrtyper.originalconcretetype(hop.s_result))
     try:
@@ -60,7 +60,7 @@
     if opdesc.canfold and argbox.is_constant():
         arg = rvalue.ll_getvalue(argbox, ARG0)
         res = opdesc.llop(RESULT, arg)
-        return rvalue.ll_fromvalue(res)
+        return rvalue.ll_fromvalue(jitstate, res)
     op_args = [argbox.getgenvar(jitstate.curbuilder)]
     genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
                                       opdesc.gv_RESULT)
@@ -76,7 +76,7 @@
         arg0 = rvalue.ll_getvalue(argbox0, ARG0)
         arg1 = rvalue.ll_getvalue(argbox1, ARG1)
         res = opdesc.llop(RESULT, arg0, arg1)
-        return rvalue.ll_fromvalue(res)
+        return rvalue.ll_fromvalue(jitstate, res)
     op_args = [argbox0.getgenvar(jitstate.curbuilder),
                argbox1.getgenvar(jitstate.curbuilder)]
     genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
@@ -87,7 +87,7 @@
     if fielddesc.immutable and argbox.is_constant():
         res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
                       fielddesc.fieldname)
-        return rvalue.ll_fromvalue(res)
+        return rvalue.ll_fromvalue(jitstate, res)
     assert isinstance(argbox, rvalue.PtrRedBox)
     if argbox.content is None:
         op_args = [argbox.getgenvar(jitstate.curbuilder),
@@ -104,8 +104,8 @@
         op_args = [destbox.getgenvar(jitstate.curbuilder),
                    fielddesc.fieldname_gv[-1],
                    valuebox.getgenvar(jitstate.curbuilder)]
-        jitstate.curbuilder.genop('setfield', op_args,
-                                  rgenop.gv_Void)       
+        builder = jitstate.curbuilder
+        builder.genop('setfield', op_args, builder.rgenop.gv_Void)
     else:
         destbox.content.op_setfield(jitstate, fielddesc, valuebox)
 
@@ -113,7 +113,7 @@
     if argbox.is_constant():
         res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
                       fielddesc.fieldname)
-        return rvalue.ll_fromvalue(res)
+        return rvalue.ll_fromvalue(jitstate, res)
     assert isinstance(argbox, rvalue.PtrRedBox)
     if argbox.content is None:
         op_args = [argbox.getgenvar(jitstate.curbuilder),
@@ -129,7 +129,7 @@
     if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant():
         array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
         res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
-        return rvalue.ll_fromvalue(res)
+        return rvalue.ll_fromvalue(jitstate, res)
     op_args = [argbox.getgenvar(jitstate.curbuilder),
                indexbox.getgenvar(jitstate.curbuilder)]
     genvar = jitstate.curbuilder.genop('getarrayitem', op_args,
@@ -143,6 +143,7 @@
     return builder.build_jitstate(backstate)
 
 def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes):
+    rgenop = jitstate.rgenop
     mylocalredboxes = redboxes
     redboxes = list(redboxes)
     jitstate.extend_with_parent_locals(redboxes)
@@ -158,7 +159,7 @@
         linkargs = []
         for box in outgoingvarboxes:
             linkargs.append(box.getgenvar(None))
-            box.genvar = rgenop.geninputarg(newblock, box.gv_type)
+            box.genvar = newblock.geninputarg(box.gv_type)
         jitstate.curbuilder.enter_block(linkargs, newblock)
         states_dic[key] = frozens, newblock
         return jitstate
@@ -191,7 +192,7 @@
     for box in outgoingvarboxes:
         if box.is_constant():            # constant boxes considered immutable:
             box = box.copy(replace_memo) # copy to avoid patching the original
-        box.genvar = rgenop.geninputarg(newblock, box.gv_type)
+        box.genvar = newblock.geninputarg(box.gv_type)
     if replace_memo.boxes:
         for i in range(len(mylocalredboxes)):
             newbox = redboxes[i].replace(replace_memo)
@@ -206,6 +207,7 @@
     
 def enter_block(jitstate, redboxes):
     # 'redboxes' is a fixed-size list (s_box_list) of the current red boxes
+    rgenop = jitstate.rgenop
     newblock = rgenop.newblock()
     incoming = []
     memo = rvalue.enter_block_memo()
@@ -224,6 +226,7 @@
 def dyn_enter_block(jitstate, redboxes):
     # 'redboxes' is a var-sized list (s_box_accum) of *all* the boxes
     # including the ones from the callers' locals
+    rgenop = jitstate.rgenop
     newblock = rgenop.newblock()
     incoming = []
     memo = rvalue.enter_block_memo()
@@ -269,15 +272,16 @@
         retrieve_jitstate_for_merge(cache, jitstate, (), [retbox])
     frozens, block = cache[()]
     _, returnbox = jitstate.return_queue[-1]
-    builder = ResidualGraphBuilder(block)
+    rgenop = jitstate.rgenop
+    builder = ResidualGraphBuilder(rgenop, block)
     builder.valuebox = returnbox
     return builder
 
 def ll_gvar_from_redbox(jitstate, redbox):
     return redbox.getgenvar(jitstate.curbuilder)
 
-def ll_gvar_from_constant(ll_value):
-    return rgenop.genconst(ll_value)
+def ll_gvar_from_constant(jitstate, ll_value):
+    return jitstate.rgenop.genconst(ll_value)
 
 def save_locals(jitstate, redboxes):
     jitstate.localredboxes = redboxes
@@ -292,43 +296,57 @@
 
 # ____________________________________________________________
 
-class ResidualGraphBuilder(rgenop.LowLevelOpBuilder):
-    def __init__(self, block=rgenop.nullblock, link=rgenop.nulllink):
-        rgenop.LowLevelOpBuilder.__init__(self, block)
+class ResidualGraphBuilder(object):
+    def __init__(self, rgenop, block=None, link=None):
+        self.rgenop = rgenop
+        self.block = block
         self.outgoinglink = link
         self.valuebox = None
 
+    def genconst(self, llvalue):
+        return self.rgenop.genconst(llvalue)
+    genconst._annspecialcase_ = 'specialize:ll'
+
+    def genvoidconst(self, dummy):
+        return self.rgenop.placeholder(dummy)
+    genvoidconst._annspecialcase_ = 'specialize:arg(1)'
+
+    def genop(self, opname, args_gv, gv_resulttype=None):
+        return self.block.genop(opname, args_gv, gv_resulttype)
+    genop._annspecialcase_ = 'specialize:arg(1)'
+
+    def constTYPE(self, T):
+        return self.rgenop.constTYPE(T)
+    constTYPE._annspecialcase_ = 'specialize:arg(1)'
+
     def build_jitstate(self, backstate=None):
         return JITState(self, backstate)
 
     def enter_block(self, linkargs, newblock):
-        rgenop.closelink(self.outgoinglink, linkargs, newblock)
+        self.outgoinglink.close(linkargs, newblock)
         self.block = newblock
-        self.outgoinglink = rgenop.nulllink
+        self.outgoinglink = None
    
     def leave_block(self):
-        self.outgoinglink = rgenop.closeblock1(self.block)
+        self.outgoinglink = self.block.close1()
 
     def leave_block_split(self, exitgvar):
-        false_link, true_link = rgenop.closeblock2(self.block, exitgvar)    
-        later_builder = ResidualGraphBuilder(link=false_link)
+        false_link, true_link = self.block.close2(exitgvar)    
+        later_builder = ResidualGraphBuilder(self.rgenop, link=false_link)
         self.outgoinglink = true_link
         return later_builder
 
     def finish_and_goto(self, linkargs, targetblock):
-        rgenop.closelink(self.outgoinglink, linkargs, targetblock)
-        self.outgoinglink = rgenop.nulllink
+        self.outgoinglink.close(linkargs, targetblock)
+        self.outgoinglink = None
         
     def finish_and_return(self):
         gv_retval = self.valuebox.getgenvar(self)
-        returnlink = rgenop.closeblock1(self.block)
-        rgenop.closereturnlink(returnlink, gv_retval)
-        
-    def clone(self):
-        XXX
+        returnlink = self.block.close1()
+        returnlink.closereturn(gv_retval)
 
-def ll_make_builder():
-    return ResidualGraphBuilder(rgenop.newblock())
+def make_builder(rgenop):
+    return ResidualGraphBuilder(rgenop, rgenop.newblock())
 
 def ll_int_box(gv_type, gv):
     return rvalue.IntRedBox(gv_type, gv)
@@ -340,7 +358,7 @@
     return rvalue.PtrRedBox(gv_type, gv)
 
 def ll_geninputarg(builder, gv_TYPE):
-    return rgenop.geninputarg(builder.block, gv_TYPE)
+    return builder.block.geninputarg(gv_TYPE)
 
 def ll_end_setup_builder(builder):
     builder.leave_block()
@@ -357,6 +375,7 @@
         self.split_queue = []
         self.return_queue = []
         self.curbuilder = builder
+        self.rgenop = builder.rgenop
         self.backstate = backstate
 
     def extend_with_parent_locals(self, redboxes):

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Wed Aug 23 18:47:27 2006
@@ -8,7 +8,6 @@
 from pypy.rpython.lltypesystem.rstr import string_repr
 from pypy.rpython.typesystem import LowLevelTypeSystem
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython import rgenop
 from pypy.jit.hintannotator import model as hintmodel
 from pypy.jit.hintannotator import container as hintcontainer
 from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer
@@ -40,6 +39,7 @@
         self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy()
         self.red_reprs = {}
         self.timeshifter = timeshifter
+        self.RGenOp = timeshifter.RGenOp
 
     originalconcretetype = staticmethod(originalconcretetype)
 
@@ -127,11 +127,11 @@
         ts = self.timeshifter
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
-        fielddesc = rcontainer.StructTypeDesc(PTRTYPE.TO).getfielddesc(c_fieldname.value)
+        structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
+        fielddesc = structdesc.getfielddesc(c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
-        s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getfield,
             [ts.s_JITState, s_fielddesc, ts.s_RedBox],
             [v_jitstate,    c_fielddesc, v_argbox   ],
@@ -147,11 +147,10 @@
         ts = self.timeshifter
         v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
                                           self.getredrepr(lltype.Signed))
-        fielddesc = rcontainer.ArrayFieldDesc(PTRTYPE)
+        fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
-        s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getarrayitem,
             [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
             [v_jitstate,    c_fielddesc, v_argbox,    v_index    ],
@@ -168,11 +167,11 @@
                                                            green_void_repr,
                                                            self.getredrepr(VALUETYPE)
                                                            )
-        fielddesc = rcontainer.StructTypeDesc(PTRTYPE.TO).getfielddesc(c_fieldname.value)
+        structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
+        fielddesc = structdesc.getfielddesc(c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
-        s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_setfield,
             [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
             [v_jitstate,    c_fielddesc, v_destbox,   v_valuebox],
@@ -186,11 +185,11 @@
         PTRTYPE = originalconcretetype(hop.args_s[0])
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
-        fielddesc = rcontainer.NamedFieldDesc(PTRTYPE, c_fieldname.value) # XXX
+        fielddesc = rcontainer.NamedFieldDesc(self.RGenOp, PTRTYPE,
+                                              c_fieldname.value) # XXX
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
-        s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getsubstruct,
             [ts.s_JITState, s_fielddesc, ts.s_RedBox],
             [v_jitstate,    c_fielddesc, v_argbox   ],
@@ -257,7 +256,7 @@
 
     def handle_highlevel_operation(self, fnobj, hop):
         from pypy.jit.timeshifter.oop import OopSpecDesc, Index
-        oopspecdesc = OopSpecDesc(fnobj)
+        oopspecdesc = OopSpecDesc(self.RGenOp, fnobj)
 
         args_v = []
         for obj in oopspecdesc.argtuple:
@@ -424,10 +423,11 @@
         return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox,
                        [ts.s_JITState, llops.timeshifter.s_RedBox],
                        [v_jitstate,    v],
-                       annmodel.SomePtr(rgenop.CONSTORVAR))
+                       ts.s_ConstOrVar)
 
     def convert_const(self, ll_value):
-        redbox = rvalue.ll_fromvalue(ll_value)
+        RGenOp = self.timeshifter.RGenOp
+        redbox = rvalue.redbox_from_prebuilt_value(RGenOp, ll_value)
         timeshifter = self.timeshifter
         return timeshifter.annhelper.delayedconst(timeshifter.r_RedBox, redbox)
 
@@ -439,10 +439,10 @@
     typedesc = None
 
     def create(self, hop):
+        ts = self.timeshifter
         if self.typedesc is None:
             T = self.original_concretetype.TO
-            self.typedesc = rcontainer.StructTypeDesc(T)
-        ts = self.timeshifter
+            self.typedesc = rcontainer.StructTypeDesc(ts.RGenOp, T)
         return hop.llops.genmixlevelhelpercall(self.typedesc.ll_factory,
             [], [], ts.s_RedBox)
 
@@ -597,9 +597,12 @@
             return annmodel.SomeInteger()
 
     def get_genop_var(self, v, llops):
+        ts = self.timeshifter
+        v_jitstate = hop.llops.getjitstate()
         return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant,
-                                           [self.annotation()], [v],
-                                           annmodel.SomePtr(rgenop.CONSTORVAR))
+                                           [ts.s_JITState, self.annotation()],
+                                           [v_jitstate,    v],
+                                           ts.s_ConstOrVar)
 
     def convert_const(self, ll_value):
         return ll_value
@@ -624,9 +627,12 @@
 
     def convert_from_to((r_from, r_to), v, llops):
         assert r_from.lowleveltype == r_to.original_concretetype
+        ts = llops.timeshifter
+        v_jitstate = llops.getjitstate()
         return llops.genmixlevelhelpercall(rvalue.ll_fromvalue,
-                                           [r_from.annotation()], [v],
-                                           llops.timeshifter.s_RedBox)
+                        [ts.s_JITState, r_from.annotation()],
+                        [v_jitstate,    v],
+                        llops.timeshifter.s_RedBox)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Wed Aug 23 18:47:27 2006
@@ -1,4 +1,3 @@
-from pypy.rpython import rgenop
 from pypy.rpython.lltypesystem import lltype, llmemory
 
 class Memo(object):
@@ -14,8 +13,8 @@
 def freeze_memo():
     return Memo()
 
-def unfreeze_memo():
-    return {} # Memo()
+##def unfreeze_memo():
+##    return {} # Memo()
 
 def exactmatch_memo():
     return Memo()
@@ -26,19 +25,20 @@
 
 class RedBox(object):
 
-    def __init__(self, gv_type, genvar=rgenop.nullvar):
-        assert rgenop.isconst(gv_type)   # temporary?
+    def __init__(self, gv_type, genvar=None):
+        assert gv_type.is_const
         self.gv_type = gv_type
-        self.genvar = genvar    # nullvar or a genvar
+        self.genvar = genvar    # None or a genvar
 
     def __repr__(self):
         if not self.genvar:
             return '<dummy>'
         else:
+            from pypy.jit.codegen.llgraph.rgenop import rgenop
             return '<%r>' % (rgenop.reveal(self.genvar),)
 
     def is_constant(self):
-        return bool(self.genvar) and rgenop.isconst(self.genvar)
+        return bool(self.genvar) and self.genvar.is_const
 
     def getgenvar(self, builder):
         return self.genvar
@@ -48,7 +48,7 @@
         if not self.is_constant() and self not in memo:
             incoming.append(self.genvar)
             memo[self] = None
-            self.genvar = rgenop.geninputarg(newblock, self.gv_type)
+            self.genvar = newblock.geninputarg(self.gv_type)
 
     def replace(self, memo):
         memo = memo.boxes
@@ -83,17 +83,25 @@
         # XXX what about long longs?
         return redboxbuilder_int
 
-def ll_fromvalue(value):
+def ll_fromvalue(jitstate, value):
     "Make a constant RedBox from a low-level value."
+    rgenop = jitstate.rgenop
     T = lltype.typeOf(value)
     gv_type = rgenop.constTYPE(T)
     gv = rgenop.genconst(value)
     cls = ll_redboxcls(T)
     return cls(gv_type, gv)
 
+def redbox_from_prebuilt_value(RGenOp, value):
+    T = lltype.typeOf(value)
+    gv_type = RGenOp.constTYPE(T)
+    gv = RGenOp.constPrebuiltGlobal(value)
+    cls = ll_redboxcls(T)
+    return cls(gv_type, gv)
+
 def ll_getvalue(box, T):
     "Return the content of a known-to-be-constant RedBox."
-    return rgenop.revealconst(T, box.genvar)
+    return box.genvar.revealconst(T)
 
 
 class IntRedBox(RedBox):
@@ -216,17 +224,17 @@
     def __init__(self, gv_const):
         self.gv_const = gv_const
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            box = memo[self] = IntRedBox(gv_type, self.gv_const)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            box = memo[self] = IntRedBox(gv_type, self.gv_const)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         if (box.is_constant() and
-            rgenop.revealconst(lltype.Signed, self.gv_const) ==
-            rgenop.revealconst(lltype.Signed, box.genvar)):
+            self.gv_const.revealconst(lltype.Signed) ==
+               box.genvar.revealconst(lltype.Signed)):
             return True
         else:
             outgoingvarboxes.append(box)
@@ -235,13 +243,13 @@
 
 class FrozenIntVar(FrozenValue):
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            gv_value = rgenop.geninputarg(block, gv_type)
-            box = memo[self] = IntRedBox(gv_type, gv_value)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            gv_value = rgenop.geninputarg(block, gv_type)
+##            box = memo[self] = IntRedBox(gv_type, gv_value)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         memo = memo.boxes
@@ -261,17 +269,17 @@
     def __init__(self, gv_const):
         self.gv_const = gv_const
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            box = memo[self] = DoubleRedBox(gv_type, self.gv_const)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            box = memo[self] = DoubleRedBox(gv_type, self.gv_const)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         if (box.is_constant() and
-            rgenop.revealconst(lltype.Float, self.gv_const) ==
-            rgenop.revealconst(lltype.Float, box.genvar)):
+            self.gv_const.revealconst(lltype.Float) ==
+               box.genvar.revealconst(lltype.Float)):
             return True
         else:
             outgoingvarboxes.append(box)
@@ -280,13 +288,13 @@
 
 class FrozenDoubleVar(FrozenValue):
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            gv_value = rgenop.geninputarg(block, gv_type)
-            box = memo[self] = DoubleRedBox(gv_type, gv_value)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            gv_value = rgenop.geninputarg(block, gv_type)
+##            box = memo[self] = DoubleRedBox(gv_type, gv_value)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         memo = memo.boxes
@@ -306,17 +314,17 @@
     def __init__(self, gv_const):
         self.gv_const = gv_const
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            box = memo[self] = PtrRedBox(gv_type, self.gv_const)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            box = memo[self] = PtrRedBox(gv_type, self.gv_const)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         if (box.is_constant() and
-            rgenop.revealconst(llmemory.Address, self.gv_const) ==
-            rgenop.revealconst(llmemory.Address, box.genvar)):
+            self.gv_const.revealconst(llmemory.Address) ==
+               box.genvar.revealconst(llmemory.Address)):
             return True
         else:
             outgoingvarboxes.append(box)
@@ -325,13 +333,13 @@
 
 class FrozenPtrVar(FrozenValue):
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            gv_value = rgenop.geninputarg(block, gv_type)
-            box = memo[self] = PtrRedBox(gv_type, gv_value)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            gv_value = rgenop.geninputarg(block, gv_type)
+##            box = memo[self] = PtrRedBox(gv_type, gv_value)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         memo = memo.boxes
@@ -348,13 +356,13 @@
 
 class FrozenPtrVirtual(FrozenValue):
 
-    def unfreeze(self, memo, block, gv_type):
-        try:
-            return memo[self]
-        except KeyError:
-            box = memo[self] = PtrRedBox(gv_type)
-            box.content = self.fz_content.unfreeze(memo, block)
-            return box
+##    def unfreeze(self, memo, block, gv_type):
+##        try:
+##            return memo[self]
+##        except KeyError:
+##            box = memo[self] = PtrRedBox(gv_type)
+##            box.content = self.fz_content.unfreeze(memo, block)
+##            return box
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         assert isinstance(box, PtrRedBox)

Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	Wed Aug 23 18:47:27 2006
@@ -9,7 +9,6 @@
 from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.objectmodel import hint, keepalive_until_here
-from pypy.rpython import rgenop
 from pypy.rpython.lltypesystem import rstr
 from pypy.annotation import model as annmodel
 from pypy.rpython.llinterp import LLInterpreter
@@ -45,547 +44,533 @@
         hannotator.translator.view()
     return hs, hannotator, rtyper
 
-_cache = {}
-_cache_order = []
-def timeshift_cached(ll_function, values, inline, policy):
-    key = ll_function, inline, policy
-    try:
-        result, argtypes = _cache[key]
-    except KeyError:
-        if len(_cache_order) >= 3:
-            del _cache[_cache_order.pop(0)]
-        hs, ha, rtyper = hannotate(ll_function, values,
-                                   inline=inline, policy=policy)
-        htshift = HintTimeshift(ha, rtyper)
-        htshift.timeshift()
-        t = rtyper.annotator.translator
-        for graph in ha.translator.graphs:
-            checkgraph(graph)
-            t.graphs.append(graph)
-        if conftest.option.view:
-            from pypy.translator.tool.graphpage import FlowGraphPage
-            FlowGraphPage(t, ha.translator.graphs).display()
-        result = hs, ha, rtyper, htshift
-        _cache[key] = result, getargtypes(rtyper.annotator, values)
-        _cache_order.append(key)
-    else:
-        hs, ha, rtyper, htshift = result
-        assert argtypes == getargtypes(rtyper.annotator, values)
-    return result
-
-def timeshift(ll_function, values, opt_consts=[], inline=None, policy=None):
-    hs, ha, rtyper, htshift = timeshift_cached(ll_function, values,
-                                               inline, policy)
-    # run the time-shifted graph-producing graphs
-    graph1 = ha.translator.graphs[0]
-    llinterp = LLInterpreter(rtyper)
-    builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
-    graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
-    residual_graph_args = []
-    assert len(graph1.getargs()) == 2 + len(values)
-    for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
-        r = htshift.hrtyper.bindingrepr(v)
-        residual_v = r.residual_values(llvalue)
-        if len(residual_v) == 0:
-            # green
-            graph1args.append(llvalue)
+class TimeshiftingTests(object):
+    from pypy.jit.codegen.llgraph.rgenop import RGenOp
+
+    def setup_class(cls):
+        cls._cache = {}
+        cls._cache_order = []
+
+    def teardown_class(cls):
+        del cls._cache
+        del cls._cache_order
+
+    def timeshift_cached(self, ll_function, values, inline, policy):
+        key = ll_function, inline, policy
+        try:
+            result, argtypes = self._cache[key]
+        except KeyError:
+            if len(self._cache_order) >= 3:
+                del self._cache[self._cache_order.pop(0)]
+            hs, ha, rtyper = hannotate(ll_function, values,
+                                       inline=inline, policy=policy)
+            htshift = HintTimeshift(ha, rtyper, self.RGenOp)
+            htshift.timeshift()
+            t = rtyper.annotator.translator
+            for graph in ha.translator.graphs:
+                checkgraph(graph)
+                t.graphs.append(graph)
+            if conftest.option.view:
+                from pypy.translator.tool.graphpage import FlowGraphPage
+                FlowGraphPage(t, ha.translator.graphs).display()
+            result = hs, ha, rtyper, htshift
+            self._cache[key] = result, getargtypes(rtyper.annotator, values)
+            self._cache_order.append(key)
         else:
-            # red
-            assert residual_v == [llvalue], "XXX for now"
-            TYPE = htshift.originalconcretetype(v)
-            gv_type = rgenop.constTYPE(TYPE)
-            gvar = llinterp.eval_graph(htshift.ll_geninputarg_graph, [builder,
-                                                                      gv_type])
-            if i in opt_consts: # XXX what should happen here interface wise is unclear
-                gvar = rgenop.genconst(llvalue)
-            if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
-                ll_box_graph = htshift.ll_addr_box_graph
-            elif isinstance(llvalue, float):
-                ll_box_graph = htshift.ll_double_box_graph
+            hs, ha, rtyper, htshift = result
+            assert argtypes == getargtypes(rtyper.annotator, values)
+        return result
+
+    def timeshift(self, ll_function, values, opt_consts=[], inline=None,
+                  policy=None):
+        hs, ha, rtyper, htshift = self.timeshift_cached(ll_function, values,
+                                                        inline, policy)
+        # run the time-shifted graph-producing graphs
+        graph1 = ha.translator.graphs[0]
+        llinterp = LLInterpreter(rtyper)
+        builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
+        graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
+        residual_graph_args = []
+        assert len(graph1.getargs()) == 2 + len(values)
+        for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
+            r = htshift.hrtyper.bindingrepr(v)
+            residual_v = r.residual_values(llvalue)
+            if len(residual_v) == 0:
+                # green
+                graph1args.append(llvalue)
             else:
-                ll_box_graph = htshift.ll_int_box_graph
-            box = llinterp.eval_graph(ll_box_graph, [gv_type, gvar])
-            graph1args.append(box)
-            residual_graph_args.append(llvalue)
-    startblock = llinterp.eval_graph(htshift.ll_end_setup_builder_graph, [builder])
-
-    builder = llinterp.eval_graph(graph1, graph1args)
-    r = htshift.hrtyper.getrepr(hs)
-    llinterp.eval_graph(htshift.ll_close_builder_graph, [builder])
-
-    # now try to run the blocks produced by the builder
-    residual_graph = rgenop.buildgraph(startblock)
-    insns = summary(residual_graph)
-    res = rgenop.testgengraph(residual_graph, residual_graph_args,
-                              viewbefore = conftest.option.view)
-    return insns, res
-
-##def test_ll_get_return_queue():
-##    t = TranslationContext()
-##    a = t.buildannotator()
-##    rtyper = t.buildrtyper()
-##    rtyper.specialize() # XXX
-
-##    htshift = HintTimeshift(None, rtyper)
-
-##    questate = htshift.QUESTATE_PTR.TO.ll_newstate()
-
-##    def llf(questate):
-##        return questate.ll_get_return_queue()
-
-##    from pypy.rpython import annlowlevel
-
-##    graph = annlowlevel.annotate_mixlevel_helper(rtyper, llf, [
-##        annmodel.SomePtr(htshift.QUESTATE_PTR)])
-
-##    s = a.binding(graph.getreturnvar())
-
-##    assert s == htshift.s_return_queue
-
-##    rtyper.specialize_more_blocks()
-
-##    llinterp = LLInterpreter(rtyper)
-##    rq = llinterp.eval_graph(graph, [questate])
-##    assert lltype.typeOf(rq) == rtyper.getrepr(s).lowleveltype
-
-
-def test_simple_fixed():
-    py.test.skip("green return not working")
-    def ll_function(x, y):
-        return hint(x + y, concrete=True)
-    insns, res = timeshift(ll_function, [5, 7])
-    assert res == 12
-    assert insns == {}
-
-def test_very_simple():
-    def ll_function(x, y):
-        return x + y
-    insns, res = timeshift(ll_function, [5, 7])
-    assert res == 12
-    assert insns == {'int_add': 1}
-
-def test_convert_const_to_redbox():
-    def ll_function(x, y):
-        x = hint(x, concrete=True)
-        tot = 0
-        while x:    # conversion from green '0' to red 'tot'
-            tot += y
-            x -= 1
-        return tot
-    insns, res = timeshift(ll_function, [7, 2])
-    assert res == 14
-    assert insns == {'int_add': 7}
-
-def test_simple_opt_const_propagation2():
-    def ll_function(x, y):
-        return x + y
-    insns, res = timeshift(ll_function, [5, 7], [0, 1])
-    assert res == 12
-    assert insns == {}
-
-def test_simple_opt_const_propagation1():
-    def ll_function(x):
-        return -x
-    insns, res = timeshift(ll_function, [5], [0])
-    assert res == -5
-    assert insns == {}
-
-def test_loop_folding():
-    def ll_function(x, y):
-        tot = 0
-        x = hint(x, concrete=True)        
-        while x:
-            tot += y
-            x -= 1
-        return tot
-    insns, res = timeshift(ll_function, [7, 2], [0, 1])
-    assert res == 14
-    assert insns == {}
-
-def test_loop_merging():
-    def ll_function(x, y):
-        tot = 0
-        while x:
-            tot += y
+                # red
+                assert residual_v == [llvalue], "XXX for now"
+                TYPE = htshift.originalconcretetype(v)
+                gv_type = self.RGenOp.constTYPE(TYPE)
+                ll_type = htshift.r_ConstOrVar.convert_const(gv_type)
+                ll_gvar = llinterp.eval_graph(htshift.ll_geninputarg_graph,
+                                              [builder, ll_type])
+                if i in opt_consts: # XXX what should happen here interface wise is unclear
+                    gvar = self.RGenOp.constPrebuiltGlobal(llvalue)
+                    ll_gvar = htshift.r_ConstOrVar.convert_const(gvar)
+                if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
+                    ll_box_graph = htshift.ll_addr_box_graph
+                elif isinstance(llvalue, float):
+                    ll_box_graph = htshift.ll_double_box_graph
+                else:
+                    ll_box_graph = htshift.ll_int_box_graph
+                box = llinterp.eval_graph(ll_box_graph, [ll_type, ll_gvar])
+                graph1args.append(box)
+                residual_graph_args.append(llvalue)
+        startblock = llinterp.eval_graph(htshift.ll_end_setup_builder_graph, [builder])
+
+        builder = llinterp.eval_graph(graph1, graph1args)
+        r = htshift.hrtyper.getrepr(hs)
+        llinterp.eval_graph(htshift.ll_close_builder_graph, [builder])
+
+        # now try to run the blocks produced by the builder
+        residual_graph = self.RGenOp.buildgraph(startblock)
+        insns = summary(residual_graph)
+        res = self.RGenOp.testgengraph(residual_graph, residual_graph_args,
+                                       viewbefore = conftest.option.view)
+        return insns, res
+
+
+class TestTimeshift(TimeshiftingTests):
+
+    def test_simple_fixed(self):
+        py.test.skip("green return not working")
+        def ll_function(x, y):
+            return hint(x + y, concrete=True)
+        insns, res = self.timeshift(ll_function, [5, 7])
+        assert res == 12
+        assert insns == {}
+
+    def test_very_simple(self):
+        def ll_function(x, y):
+            return x + y
+        insns, res = self.timeshift(ll_function, [5, 7])
+        assert res == 12
+        assert insns == {'int_add': 1}
+
+    def test_convert_const_to_redbox(self):
+        def ll_function(x, y):
+            x = hint(x, concrete=True)
+            tot = 0
+            while x:    # conversion from green '0' to red 'tot'
+                tot += y
+                x -= 1
+            return tot
+        insns, res = self.timeshift(ll_function, [7, 2])
+        assert res == 14
+        assert insns == {'int_add': 7}
+
+    def test_simple_opt_const_propagation2(self):
+        def ll_function(x, y):
+            return x + y
+        insns, res = self.timeshift(ll_function, [5, 7], [0, 1])
+        assert res == 12
+        assert insns == {}
+
+    def test_simple_opt_const_propagation1(self):
+        def ll_function(x):
+            return -x
+        insns, res = self.timeshift(ll_function, [5], [0])
+        assert res == -5
+        assert insns == {}
+
+    def test_loop_folding(self):
+        def ll_function(x, y):
+            tot = 0
+            x = hint(x, concrete=True)        
+            while x:
+                tot += y
+                x -= 1
+            return tot
+        insns, res = self.timeshift(ll_function, [7, 2], [0, 1])
+        assert res == 14
+        assert insns == {}
+
+    def test_loop_merging(self):
+        def ll_function(x, y):
+            tot = 0
+            while x:
+                tot += y
+                x -= 1
+            return tot
+        insns, res = self.timeshift(ll_function, [7, 2], [])
+        assert res == 14
+        assert insns['int_add'] == 2
+        assert insns['int_is_true'] == 2
+
+        insns, res = self.timeshift(ll_function, [7, 2], [0])
+        assert res == 14
+        assert insns['int_add'] == 2
+        assert insns['int_is_true'] == 1
+
+        insns, res = self.timeshift(ll_function, [7, 2], [1])
+        assert res == 14
+        assert insns['int_add'] == 1
+        assert insns['int_is_true'] == 2
+
+        insns, res = self.timeshift(ll_function, [7, 2], [0, 1])
+        assert res == 14
+        assert insns['int_add'] == 1
+        assert insns['int_is_true'] == 1
+
+    def test_two_loops_merging(self):
+        def ll_function(x, y):
+            tot = 0
+            while x:
+                tot += y
+                x -= 1
+            while y:
+                tot += y
+                y -= 1
+            return tot
+        insns, res = self.timeshift(ll_function, [7, 3], [])
+        assert res == 27
+        assert insns['int_add'] == 3
+        assert insns['int_is_true'] == 3
+
+    def test_convert_greenvar_to_redvar(self):
+        def ll_function(x, y):
+            hint(x, concrete=True)
+            return x - y
+        insns, res = self.timeshift(ll_function, [70, 4], [0])
+        assert res == 66
+        assert insns['int_sub'] == 1
+        insns, res = self.timeshift(ll_function, [70, 4], [0, 1])
+        assert res == 66
+        assert insns == {}
+
+    def test_green_across_split(self):
+        def ll_function(x, y):
+            hint(x, concrete=True)
+            if y > 2:
+                z = x - y
+            else:
+                z = x + y
+            return z
+        insns, res = self.timeshift(ll_function, [70, 4], [0])
+        assert res == 66
+        assert insns['int_add'] == 1
+        assert insns['int_sub'] == 1
+
+    def test_merge_const_before_return(self):
+        def ll_function(x):
+            if x > 0:
+                y = 17
+            else:
+                y = 22
             x -= 1
-        return tot
-    insns, res = timeshift(ll_function, [7, 2], [])
-    assert res == 14
-    assert insns['int_add'] == 2
-    assert insns['int_is_true'] == 2
-
-    insns, res = timeshift(ll_function, [7, 2], [0])
-    assert res == 14
-    assert insns['int_add'] == 2
-    assert insns['int_is_true'] == 1
-
-    insns, res = timeshift(ll_function, [7, 2], [1])
-    assert res == 14
-    assert insns['int_add'] == 1
-    assert insns['int_is_true'] == 2
-
-    insns, res = timeshift(ll_function, [7, 2], [0, 1])
-    assert res == 14
-    assert insns['int_add'] == 1
-    assert insns['int_is_true'] == 1
-
-def test_two_loops_merging():
-    def ll_function(x, y):
-        tot = 0
-        while x:
-            tot += y
+            y += 1
+            return y+x
+        insns, res = self.timeshift(ll_function, [-70], [])
+        assert res == 23-71
+        assert insns == {'int_gt': 1, 'int_add': 2, 'int_sub': 2}
+
+    def test_merge_3_redconsts_before_return(self):
+        def ll_function(x):
+            if x > 2:
+                y = hint(54, variable=True)
+            elif x > 0:
+                y = hint(17, variable=True)
+            else:
+                y = hint(22, variable=True)
             x -= 1
-        while y:
-            tot += y
-            y -= 1
-        return tot
-    insns, res = timeshift(ll_function, [7, 3], [])
-    assert res == 27
-    assert insns['int_add'] == 3
-    assert insns['int_is_true'] == 3
-
-def test_convert_greenvar_to_redvar():
-    def ll_function(x, y):
-        hint(x, concrete=True)
-        return x - y
-    insns, res = timeshift(ll_function, [70, 4], [0])
-    assert res == 66
-    assert insns['int_sub'] == 1
-    insns, res = timeshift(ll_function, [70, 4], [0, 1])
-    assert res == 66
-    assert insns == {}
-
-def test_green_across_split():
-    def ll_function(x, y):
-        hint(x, concrete=True)
-        if y > 2:
-            z = x - y
-        else:
-            z = x + y
-        return z
-    insns, res = timeshift(ll_function, [70, 4], [0])
-    assert res == 66
-    assert insns['int_add'] == 1
-    assert insns['int_sub'] == 1
-
-def test_merge_const_before_return():
-    def ll_function(x):
-        if x > 0:
-            y = 17
-        else:
-            y = 22
-        x -= 1
-        y += 1
-        return y+x
-    insns, res = timeshift(ll_function, [-70], [])
-    assert res == 23-71
-    assert insns == {'int_gt': 1, 'int_add': 2, 'int_sub': 2}
-
-def test_merge_3_redconsts_before_return():
-    def ll_function(x):
-        if x > 2:
-            y = hint(54, variable=True)
-        elif x > 0:
-            y = hint(17, variable=True)
-        else:
-            y = hint(22, variable=True)
-        x -= 1
-        y += 1
-        return y+x
-    insns, res = timeshift(ll_function, [-70], [])
-    assert res == ll_function(-70)
-    insns, res = timeshift(ll_function, [1], [])
-    assert res == ll_function(1)
-    insns, res = timeshift(ll_function, [-70], [])
-    assert res == ll_function(-70)
-
-def test_merge_const_at_return():
-    py.test.skip("green return")
-    def ll_function(x):
-        if x > 0:
-            return 17
-        else:
-            return 22
-    insns, res = timeshift(ll_function, [-70], [])
-    assert res == 22
-    assert insns == {'int_gt': 1}
-
-def test_arith_plus_minus():
-    def ll_plus_minus(encoded_insn, nb_insn, x, y):
-        acc = x
-        pc = 0
-        while pc < nb_insn:
-            op = (encoded_insn >> (pc*4)) & 0xF
-            op = hint(op, concrete=True)
-            if op == 0xA:
-                acc += y
-            elif op == 0x5:
-                acc -= y
-            pc += 1
-        return acc
-    assert ll_plus_minus(0xA5A, 3, 32, 10) == 42
-    insns, res = timeshift(ll_plus_minus, [0xA5A, 3, 32, 10], [0, 1])
-    assert res == 42
-    assert insns == {'int_add': 2,
-                     'int_sub': 1}
-
-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
-    s1 = lltype.malloc(S)
-    s1.hello = 6
-    s1.world = 7
-    insns, res = timeshift(ll_function, [s1], [])
-    assert res == 42
-    assert insns == {'getfield': 2,
-                     'int_mul': 1}
-    insns, res = timeshift(ll_function, [s1], [0])
-    assert res == 42
-    assert insns == {}
-
-def test_simple_array():
-    A = lltype.GcArray(lltype.Signed, 
-                        hints={'immutable': True})
-    def ll_function(a):
-        return a[0] * a[1]
-    a1 = lltype.malloc(A, 2)
-    a1[0] = 6
-    a1[1] = 7
-    insns, res = timeshift(ll_function, [a1], [])
-    assert res == 42
-    assert insns == {'getarrayitem': 2,
-                     'int_mul': 1}
-    insns, res = timeshift(ll_function, [a1], [0])
-    assert res == 42
-    assert insns == {}
-
-def test_simple_struct_malloc():
-    py.test.skip("blue containers: to be reimplemented")
-    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
-
-    insns, res = timeshift(ll_function, [3], [])
-    assert res == 3
-    assert insns == {'int_add': 1}
-
-    insns, res = timeshift(ll_function, [3], [0])
-    assert res == 3
-    assert insns == {}
-
-def test_inlined_substructure():
-    py.test.skip("blue containers: to be reimplemented")
-    S = lltype.Struct('S', ('n', lltype.Signed))
-    T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-    def ll_function(k):
-        t = lltype.malloc(T)
-        t.s.n = k
-        l = t.s.n
-        return l
-    insns, res = timeshift(ll_function, [7], [])
-    assert res == 7
-    assert insns == {}
-
-    insns, res = timeshift(ll_function, [7], [0])
-    assert res == 7
-    assert insns == {}    
-
-def test_degenerated_before_return():
-    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
-        s.n += 1
-        return s.n * t.s.n
-    insns, res = timeshift(ll_function, [0], [])
-    assert res == 5 * 3
-    insns, res = timeshift(ll_function, [1], [])
-    assert res == 4 * 4
-
-def test_degenerated_before_return_2():
-    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:
-            pass
-        else:
-            s = t.s
-        s.n += 1
-        return s.n * t.s.n
-    insns, res = timeshift(ll_function, [1], [])
-    assert res == 5 * 3
-    insns, res = timeshift(ll_function, [0], [])
-    assert res == 4 * 4
-
-def test_degenerated_at_return():
-    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.n = 3.25
-        t.s.n = 3
-        s = lltype.malloc(S)
-        s.n = 4
-        if flag:
-            s = t.s
-        return s
-    insns, res = timeshift(ll_function, [0], [])
-    assert res.n == 4
-    assert lltype.parentlink(res._obj) == (None, None)
-    insns, res = timeshift(ll_function, [1], [])
-    assert res.n == 3
-    parent, parentindex = lltype.parentlink(res._obj)
-    assert parentindex == 's'
-    assert parent.n == 3.25
-
-def test_degenerated_via_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 = 7
-        if flag:
-            pass
-        else:
-            s = t.s
-        t.s.n += 1
-        return s.n * t.s.n
-    insns, res = timeshift(ll_function, [1], [])
-    assert res == 7 * 4
-    insns, res = timeshift(ll_function, [0], [])
-    assert res == 4 * 4
-
-def test_plus_minus_all_inlined():
-    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
-    s = rstr.string_repr.convert_const("+-+")
-    insns, res = timeshift(ll_plus_minus, [s, 0, 2], [0], inline=999)
-    assert res == ll_plus_minus("+-+", 0, 2)
-    assert insns == {'int_add': 2, 'int_sub': 1}
-
-def test_red_virtual_container():
-    # this checks that red boxes are able to be virtualized dynamically by
-    # the compiler (the P_NOVIRTUAL policy prevents the hint-annotator from
-    # marking variables in blue)
-    S = lltype.GcStruct('S', ('n', lltype.Signed))
-    def ll_function(n):
-        s = lltype.malloc(S)
-        s.n = n
-        return s.n
-    insns, res = timeshift(ll_function, [42], [], policy=P_NOVIRTUAL)
-    assert res == 42
-    assert insns == {}
-
-def test_red_propagate():
-    S = lltype.GcStruct('S', ('n', lltype.Signed))
-    def ll_function(n, k):
-        s = lltype.malloc(S)
-        s.n = n
-        if k < 0:
-            return -123
-        return s.n * k
-    insns, res = timeshift(ll_function, [3, 8], [], policy=P_NOVIRTUAL)
-    assert res == 24
-    assert insns == {'int_lt': 1, 'int_mul': 1}
-
-def test_red_subcontainer():
-    S = lltype.Struct('S', ('n', lltype.Signed))
-    T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-    def ll_function(k):
-        t = lltype.malloc(T)
-        s = t.s
-        s.n = k
-        if k < 0:
-            return -123
-        result = s.n * (k-1)
-        keepalive_until_here(t)
-        return result
-    insns, res = timeshift(ll_function, [7], [], policy=P_NOVIRTUAL)
-    assert res == 42
-    assert insns == {'int_lt': 1, 'int_mul': 1, 'int_sub': 1}
-
-def test_merge_structures():
-    S = lltype.GcStruct('S', ('n', lltype.Signed))
-    T = lltype.GcStruct('T', ('s', lltype.Ptr(S)), ('n', lltype.Signed))
+            y += 1
+            return y+x
+        insns, res = self.timeshift(ll_function, [-70], [])
+        assert res == ll_function(-70)
+        insns, res = self.timeshift(ll_function, [1], [])
+        assert res == ll_function(1)
+        insns, res = self.timeshift(ll_function, [-70], [])
+        assert res == ll_function(-70)
+
+    def test_merge_const_at_return(self):
+        py.test.skip("green return")
+        def ll_function(x):
+            if x > 0:
+                return 17
+            else:
+                return 22
+        insns, res = self.timeshift(ll_function, [-70], [])
+        assert res == 22
+        assert insns == {'int_gt': 1}
+
+    def test_arith_plus_minus(self):
+        def ll_plus_minus(encoded_insn, nb_insn, x, y):
+            acc = x
+            pc = 0
+            while pc < nb_insn:
+                op = (encoded_insn >> (pc*4)) & 0xF
+                op = hint(op, concrete=True)
+                if op == 0xA:
+                    acc += y
+                elif op == 0x5:
+                    acc -= y
+                pc += 1
+            return acc
+        assert ll_plus_minus(0xA5A, 3, 32, 10) == 42
+        insns, res = self.timeshift(ll_plus_minus, [0xA5A, 3, 32, 10], [0, 1])
+        assert res == 42
+        assert insns == {'int_add': 2,
+                         'int_sub': 1}
+
+    def test_simple_struct(self):
+        S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
+                                          ('world', lltype.Signed),
+                            hints={'immutable': True})
+        def ll_function(s):
+            return s.hello * s.world
+        s1 = lltype.malloc(S)
+        s1.hello = 6
+        s1.world = 7
+        insns, res = self.timeshift(ll_function, [s1], [])
+        assert res == 42
+        assert insns == {'getfield': 2,
+                         'int_mul': 1}
+        insns, res = self.timeshift(ll_function, [s1], [0])
+        assert res == 42
+        assert insns == {}
+
+    def test_simple_array(self):
+        A = lltype.GcArray(lltype.Signed, 
+                            hints={'immutable': True})
+        def ll_function(a):
+            return a[0] * a[1]
+        a1 = lltype.malloc(A, 2)
+        a1[0] = 6
+        a1[1] = 7
+        insns, res = self.timeshift(ll_function, [a1], [])
+        assert res == 42
+        assert insns == {'getarrayitem': 2,
+                         'int_mul': 1}
+        insns, res = self.timeshift(ll_function, [a1], [0])
+        assert res == 42
+        assert insns == {}
+
+    def test_simple_struct_malloc(self):
+        py.test.skip("blue containers: to be reimplemented")
+        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
 
-    def ll_function(flag):
-        if flag:
+        insns, res = self.timeshift(ll_function, [3], [])
+        assert res == 3
+        assert insns == {'int_add': 1}
+
+        insns, res = self.timeshift(ll_function, [3], [0])
+        assert res == 3
+        assert insns == {}
+
+    def test_inlined_substructure(self):
+        py.test.skip("blue containers: to be reimplemented")
+        S = lltype.Struct('S', ('n', lltype.Signed))
+        T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+        def ll_function(k):
+            t = lltype.malloc(T)
+            t.s.n = k
+            l = t.s.n
+            return l
+        insns, res = self.timeshift(ll_function, [7], [])
+        assert res == 7
+        assert insns == {}
+
+        insns, res = self.timeshift(ll_function, [7], [0])
+        assert res == 7
+        assert insns == {}    
+
+    def test_degenerated_before_return(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 = 1
+            s.n = 4
+            if flag:
+                s = t.s
+            s.n += 1
+            return s.n * t.s.n
+        insns, res = self.timeshift(ll_function, [0], [])
+        assert res == 5 * 3
+        insns, res = self.timeshift(ll_function, [1], [])
+        assert res == 4 * 4
+
+    def test_degenerated_before_return_2(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 = s
-            t.n = 2
-        else:
+            t.s.n = 3
             s = lltype.malloc(S)
-            s.n = 5
+            s.n = 4
+            if flag:
+                pass
+            else:
+                s = t.s
+            s.n += 1
+            return s.n * t.s.n
+        insns, res = self.timeshift(ll_function, [1], [])
+        assert res == 5 * 3
+        insns, res = self.timeshift(ll_function, [0], [])
+        assert res == 4 * 4
+
+    def test_degenerated_at_return(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 = s
-            t.n = 6
-        return t.n + t.s.n
-    insns, res = timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
-    assert res == 5 + 6
-    assert insns == {'int_is_true': 1, 'int_add': 1}
-    insns, res = timeshift(ll_function, [1], [], policy=P_NOVIRTUAL)
-    assert res == 1 + 2
-    assert insns == {'int_is_true': 1, 'int_add': 1}
-
-def test_call_simple():
-    def ll_add_one(x):
-        return x + 1
-    def ll_function(y):
-        return ll_add_one(y)
-    insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
-    assert res == 6
-    assert insns == {'int_add': 1}
-
-def test_call_2():
-    def ll_add_one(x):
-        return x + 1
-    def ll_function(y):
-        return ll_add_one(y) + y
-    insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
-    assert res == 11
-    assert insns == {'int_add': 2}
-
-def test_call_3():
-    def ll_add_one(x):
-        return x + 1
-    def ll_two(x):
-        return ll_add_one(ll_add_one(x)) - x
-    def ll_function(y):
-        return ll_two(y) * y
-    insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
-    assert res == 10
-    assert insns == {'int_add': 2, 'int_sub': 1, 'int_mul': 1}
+            t.n = 3.25
+            t.s.n = 3
+            s = lltype.malloc(S)
+            s.n = 4
+            if flag:
+                s = t.s
+            return s
+        insns, res = self.timeshift(ll_function, [0], [])
+        assert res.n == 4
+        assert lltype.parentlink(res._obj) == (None, None)
+        insns, res = self.timeshift(ll_function, [1], [])
+        assert res.n == 3
+        parent, parentindex = lltype.parentlink(res._obj)
+        assert parentindex == 's'
+        assert parent.n == 3.25
+
+    def test_degenerated_via_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 = 7
+            if flag:
+                pass
+            else:
+                s = t.s
+            t.s.n += 1
+            return s.n * t.s.n
+        insns, res = self.timeshift(ll_function, [1], [])
+        assert res == 7 * 4
+        insns, res = self.timeshift(ll_function, [0], [])
+        assert res == 4 * 4
+
+    def test_plus_minus_all_inlined(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
+        s = rstr.string_repr.convert_const("+-+")
+        insns, res = self.timeshift(ll_plus_minus, [s, 0, 2], [0], inline=999)
+        assert res == ll_plus_minus("+-+", 0, 2)
+        assert insns == {'int_add': 2, 'int_sub': 1}
+
+    def test_red_virtual_container(self):
+        # this checks that red boxes are able to be virtualized dynamically by
+        # the compiler (the P_NOVIRTUAL policy prevents the hint-annotator from
+        # marking variables in blue)
+        S = lltype.GcStruct('S', ('n', lltype.Signed))
+        def ll_function(n):
+            s = lltype.malloc(S)
+            s.n = n
+            return s.n
+        insns, res = self.timeshift(ll_function, [42], [], policy=P_NOVIRTUAL)
+        assert res == 42
+        assert insns == {}
+
+    def test_red_propagate(self):
+        S = lltype.GcStruct('S', ('n', lltype.Signed))
+        def ll_function(n, k):
+            s = lltype.malloc(S)
+            s.n = n
+            if k < 0:
+                return -123
+            return s.n * k
+        insns, res = self.timeshift(ll_function, [3, 8], [], policy=P_NOVIRTUAL)
+        assert res == 24
+        assert insns == {'int_lt': 1, 'int_mul': 1}
+
+    def test_red_subcontainer(self):
+        S = lltype.Struct('S', ('n', lltype.Signed))
+        T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+        def ll_function(k):
+            t = lltype.malloc(T)
+            s = t.s
+            s.n = k
+            if k < 0:
+                return -123
+            result = s.n * (k-1)
+            keepalive_until_here(t)
+            return result
+        insns, res = self.timeshift(ll_function, [7], [], policy=P_NOVIRTUAL)
+        assert res == 42
+        assert insns == {'int_lt': 1, 'int_mul': 1, 'int_sub': 1}
+
+    def test_merge_structures(self):
+        S = lltype.GcStruct('S', ('n', lltype.Signed))
+        T = lltype.GcStruct('T', ('s', lltype.Ptr(S)), ('n', lltype.Signed))
+
+        def ll_function(flag):
+            if flag:
+                s = lltype.malloc(S)
+                s.n = 1
+                t = lltype.malloc(T)
+                t.s = s
+                t.n = 2
+            else:
+                s = lltype.malloc(S)
+                s.n = 5
+                t = lltype.malloc(T)
+                t.s = s
+                t.n = 6
+            return t.n + t.s.n
+        insns, res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
+        assert res == 5 + 6
+        assert insns == {'int_is_true': 1, 'int_add': 1}
+        insns, res = self.timeshift(ll_function, [1], [], policy=P_NOVIRTUAL)
+        assert res == 1 + 2
+        assert insns == {'int_is_true': 1, 'int_add': 1}
+
+    def test_call_simple(self):
+        def ll_add_one(x):
+            return x + 1
+        def ll_function(y):
+            return ll_add_one(y)
+        insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+        assert res == 6
+        assert insns == {'int_add': 1}
+
+    def test_call_2(self):
+        def ll_add_one(x):
+            return x + 1
+        def ll_function(y):
+            return ll_add_one(y) + y
+        insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+        assert res == 11
+        assert insns == {'int_add': 2}
+
+    def test_call_3(self):
+        def ll_add_one(x):
+            return x + 1
+        def ll_two(x):
+            return ll_add_one(ll_add_one(x)) - x
+        def ll_function(y):
+            return ll_two(y) * y
+        insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+        assert res == 10
+        assert insns == {'int_add': 2, 'int_sub': 1, 'int_mul': 1}

Modified: pypy/dist/pypy/jit/timeshifter/test/test_tl.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tl.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tl.py	Wed Aug 23 18:47:27 2006
@@ -1,15 +1,18 @@
 from pypy.rpython.lltypesystem.rstr import string_repr
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
 from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC
 
 from pypy.jit.tl import tl
 from pypy.jit.tl.test.test_tl import FACTORIAL_SOURCE
 
 
-def test_tl():
-    import py; py.test.skip("in-progress")
-    code = tl.compile(FACTORIAL_SOURCE)
-    ll_code = string_repr.convert_const(code)
-    insns, res = timeshift(tl.interp_without_call, [ll_code, 0, 5], [0, 1],
-                           policy=P_OOPSPEC)
-    assert res == 120
+class TestTL(TimeshiftingTests):
+
+    def test_tl(self):
+        import py; py.test.skip("in-progress")
+        code = tl.compile(FACTORIAL_SOURCE)
+        ll_code = string_repr.convert_const(code)
+        insns, res = self.timeshift(tl.interp_without_call,
+                                    [ll_code, 0, 5], [0, 1],
+                                    policy=P_OOPSPEC)
+        assert res == 120

Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tlr.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tlr.py	Wed Aug 23 18:47:27 2006
@@ -1,11 +1,14 @@
 from pypy.rpython.lltypesystem.rstr import string_repr
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
 from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC
 
 from pypy.jit.tl import tlr
 
 
-def test_tlr():
-    bytecode = string_repr.convert_const(tlr.SQUARE)
-    insns, res = timeshift(tlr.interpret, [bytecode, 9], [0], policy=P_OOPSPEC)
-    assert res == 81
+class TestTLR(TimeshiftingTests):
+
+    def test_tlr(self):
+        bytecode = string_repr.convert_const(tlr.SQUARE)
+        insns, res = self.timeshift(tlr.interpret, [bytecode, 9], [0],
+                                    policy=P_OOPSPEC)
+        assert res == 81

Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	Wed Aug 23 18:47:27 2006
@@ -1,74 +1,76 @@
 from pypy.annotation.policy import AnnotatorPolicy
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
 
 P_OOPSPEC = AnnotatorPolicy()
 P_OOPSPEC.novirtualcontainer = True
 P_OOPSPEC.oopspec = True
 
 
-def test_vlist():
-    def ll_function():
-        lst = []
-        lst.append(12)
-        return lst[0]
-    insns, res = timeshift(ll_function, [], [], policy=P_OOPSPEC)
-    assert res == 12
-    assert insns == {}
-
-def test_enter_block():
-    def ll_function(flag):
-        lst = []
-        lst.append(flag)
-        lst.append(131)
-        if flag:
+class TestVList(TimeshiftingTests):
+
+    def test_vlist(self):
+        def ll_function():
+            lst = []
+            lst.append(12)
             return lst[0]
-        else:
-            return lst[1]
-    insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
-    assert res == 6
-    assert insns == {'int_is_true': 1}
-    insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
-    assert res == 131
-    assert insns == {'int_is_true': 1}
-
-def test_merge():
-    def ll_function(flag):
-        lst = []
-        if flag:
+        insns, res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC)
+        assert res == 12
+        assert insns == {}
+
+    def test_enter_block(self):
+        def ll_function(flag):
+            lst = []
             lst.append(flag)
-        else:
             lst.append(131)
-        return lst[-1]
-    insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
-    assert res == 6
-    assert insns == {'int_is_true': 1}
-    insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
-    assert res == 131
-    assert insns == {'int_is_true': 1}
-
-def test_replace():
-    def ll_function(flag):
-        lst = []
-        if flag:
-            lst.append(12)
-        else:
-            lst.append(131)
-        return lst[-1]
-    insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
-    assert res == 12
-    assert insns == {'int_is_true': 1}
-    insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
-    assert res == 131
-    assert insns == {'int_is_true': 1}
-
-def test_force():
-    def ll_function(n):
-        lst = []
-        lst.append(n)
-        if n:
-            lst.append(12)
-        return lst[-1]
-    insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
-    assert res == 12
-    insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
-    assert res == 0
+            if flag:
+                return lst[0]
+            else:
+                return lst[1]
+        insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+        assert res == 6
+        assert insns == {'int_is_true': 1}
+        insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+        assert res == 131
+        assert insns == {'int_is_true': 1}
+
+    def test_merge(self):
+        def ll_function(flag):
+            lst = []
+            if flag:
+                lst.append(flag)
+            else:
+                lst.append(131)
+            return lst[-1]
+        insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+        assert res == 6
+        assert insns == {'int_is_true': 1}
+        insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+        assert res == 131
+        assert insns == {'int_is_true': 1}
+
+    def test_replace(self):
+        def ll_function(flag):
+            lst = []
+            if flag:
+                lst.append(12)
+            else:
+                lst.append(131)
+            return lst[-1]
+        insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+        assert res == 12
+        assert insns == {'int_is_true': 1}
+        insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+        assert res == 131
+        assert insns == {'int_is_true': 1}
+
+    def test_force(self):
+        def ll_function(n):
+            lst = []
+            lst.append(n)
+            if n:
+                lst.append(12)
+            return lst[-1]
+        insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+        assert res == 12
+        insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+        assert res == 0

Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Wed Aug 23 18:47:27 2006
@@ -1,25 +1,27 @@
-import py
+import py, types
 from pypy.rpython.lltypesystem import lltype
 from pypy.objspace.flow import model as flowmodel
 from pypy.annotation import model as annmodel
 from pypy.annotation import listdef, dictdef
 from pypy.jit.timeshifter import rvalue, oop
 from pypy.jit.timeshifter.rtimeshift import JITState, ResidualGraphBuilder
-from pypy.rpython import rmodel, rgenop, annlowlevel
+from pypy.rpython import rmodel, annlowlevel
 from pypy.rpython.lltypesystem import rtuple, rlist, rdict
 from pypy.jit.timeshifter import rtimeshift
 from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype
 from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList
 from pypy.translator.unsimplify import varoftype, copyvar
 from pypy.translator.backendopt import support
+from pypy.jit.codegen import model as cgmodel
 
 # ___________________________________________________________
 
 class HintTimeshift(object):
     
-    def __init__(self, hannotator, rtyper):
+    def __init__(self, hannotator, rtyper, RGenOp):
         self.hannotator = hannotator
         self.rtyper = rtyper
+        self.RGenOp = RGenOp
         self.hrtyper = HintRTyper(hannotator, self)
         self.latestexitindex = -1
         self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
@@ -29,6 +31,9 @@
         self.s_RedBox, self.r_RedBox = self.s_r_instanceof(rvalue.RedBox)
         self.s_OopSpecDesc, self.r_OopSpecDesc = self.s_r_instanceof(
             oop.OopSpecDesc)
+        self.s_ConstOrVar, self.r_ConstOrVar = self.s_r_instanceof(
+            cgmodel.GenVarOrConst)
+        self.s_Block, self.r_Block = self.s_r_instanceof(cgmodel.CodeGenBlock)
 
         getrepr = self.rtyper.getrepr
 
@@ -46,29 +51,33 @@
         self.r_box_accum = getrepr(self.s_box_accum)
         self.r_box_accum.setup()
 
+        def ll_make_builder():
+            rgenop = RGenOp.get_rgenop_for_testing()
+            return rtimeshift.make_builder(rgenop)
+
         self.ll_make_builder_graph = self.annhelper.getgraph(
-            rtimeshift.ll_make_builder,
+            ll_make_builder,
             [], self.s_ResidualGraphBuilder)
         self.ll_int_box_graph = self.annhelper.getgraph(
             rtimeshift.ll_int_box,
-            [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+            [self.s_ConstOrVar, self.s_ConstOrVar],
             self.s_RedBox)
         self.ll_addr_box_graph = self.annhelper.getgraph(
             rtimeshift.ll_addr_box,
-            [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+            [self.s_ConstOrVar, self.s_ConstOrVar],
             self.s_RedBox)
         self.ll_double_box_graph = self.annhelper.getgraph(
             rtimeshift.ll_int_box,
-            [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+            [self.s_ConstOrVar, self.s_ConstOrVar],
             self.s_RedBox)
         self.ll_geninputarg_graph = self.annhelper.getgraph(
             rtimeshift.ll_geninputarg,
-            [self.s_ResidualGraphBuilder, annmodel.SomePtr(rgenop.CONSTORVAR)],
-            rgenop.s_ConstOrVar)
+            [self.s_ResidualGraphBuilder, self.s_ConstOrVar],
+            self.s_ConstOrVar)
         self.ll_end_setup_builder_graph = self.annhelper.getgraph(
             rtimeshift.ll_end_setup_builder,
             [self.s_ResidualGraphBuilder],
-            annmodel.SomePtr(rgenop.BLOCK))
+            self.s_Block)
 
 ##         self.ll_close_jitstate_graph = self.annhelper.getgraph(
 ##             rtimeshift.ll_close_jitstate,
@@ -266,10 +275,12 @@
             newblock.closeblock(bridge)
         return newblock
 
-    def make_const_box(self, llops, r_green, v_value):
+    def make_const_box(self, llops, r_green, v_value, v_jitstate):
         v_box = llops.genmixlevelhelpercall(
             rvalue.ll_fromvalue,
-            [r_green.annotation()], [v_value], self.s_RedBox)
+            [self.s_JITState, r_green.annotation()],
+            [v_jitstate,      v_value],
+            self.s_RedBox)
         return v_box
         
                                                          
@@ -566,6 +577,7 @@
                                    [v_res],
                                    v_newjitstate))
         else:
+            v_jitstate = rename(orig_v_jitstate)
             args_r = []
             boxes_v = []
             for var in inputargs[1:]:
@@ -574,7 +586,7 @@
                 if isinstance(r, RedRepr):
                     boxes_v.append(var)
                 elif isinstance(r, GreenRepr):
-                    v_box = self.make_const_box(llops, r, var)
+                    v_box = self.make_const_box(llops, r, var, v_jitstate)
                     boxes_v.append(v_box)
                 else:
                     raise RuntimeError('Unsupported boxtype')
@@ -583,7 +595,6 @@
             false_exit = [exit for exit in newblock.exits if exit.exitcase is False][0]
             exitindex = self.getexitindex(false_exit, inputargs[1:], args_r, entering_links)
             c_exitindex = rmodel.inputconst(lltype.Signed, exitindex)
-            v_jitstate = rename(orig_v_jitstate)
             v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split,
                                                 [self.s_JITState,
                                                  self.s_RedBox,
@@ -665,9 +676,10 @@
         return_cache = self.return_cache
         assert return_cache is not None
         RETURN_TYPE = self.r_returnvalue.original_concretetype
+        gv_RETURN_TYPE = self.RGenOp.constTYPE(RETURN_TYPE)
         def prepare_return(jitstate):
             return rtimeshift.prepare_return(jitstate, return_cache,
-                                             rgenop.constTYPE(RETURN_TYPE))
+                                             gv_RETURN_TYPE)
         llops = HintLowLevelOpList(self, None)
         v_return_builder = llops.genmixlevelhelpercall(prepare_return,
                           [self.s_JITState], [v_jitstate2],

Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py	Wed Aug 23 18:47:27 2006
@@ -1,5 +1,4 @@
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
 from pypy.jit.timeshifter.rcontainer import AbstractContainer, cachedtype
 from pypy.jit.timeshifter import rvalue
 
@@ -7,11 +6,11 @@
 class ListTypeDesc(object):
     __metaclass__ = cachedtype
 
-    def __init__(self, LIST):
+    def __init__(self, RGenOp, LIST):
         self.LIST = LIST
         self.LISTPTR = lltype.Ptr(LIST)
-        self.gv_type = rgenop.constTYPE(self.LIST)
-        self.gv_ptrtype = rgenop.constTYPE(self.LISTPTR)
+        self.gv_type = RGenOp.constTYPE(self.LIST)
+        self.gv_ptrtype = RGenOp.constTYPE(self.LISTPTR)
         self.build_newlist = LIST.list_builder.build_newlist
         self.build_setitem = LIST.list_builder.build_setitem
 

Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Wed Aug 23 18:47:27 2006
@@ -50,7 +50,7 @@
     def __init__(pol, rtyper=None):
         pol.rtyper = rtyper
 
-    def default_specialize(pol, funcdesc, args_s):
+    def default_specialize(funcdesc, args_s):
         key = []
         new_args_s = []
         for s_obj in args_s:
@@ -69,6 +69,7 @@
         flowgraph = funcdesc.cachedgraph(tuple(key))
         args_s[:] = new_args_s
         return flowgraph
+    default_specialize = staticmethod(default_specialize)
 
     def override__init_opaque_object(pol, s_opaqueptr, s_value):
         assert isinstance(s_opaqueptr, annmodel.SomePtr)
@@ -117,7 +118,8 @@
     def default_specialize(pol, funcdesc, args_s):
         name = funcdesc.name
         if name.startswith('ll_') or name.startswith('_ll_'): # xxx can we do better?
-            return LowLevelAnnotatorPolicy.default_specialize(pol, funcdesc, args_s)
+            return super(MixLevelAnnotatorPolicy, pol).default_specialize(
+                funcdesc, args_s)
         else:
             return funcdesc.cachedgraph(None)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Wed Aug 23 18:47:27 2006
@@ -969,6 +969,8 @@
         if isinstance(self._T, (Array, FixedSizeArray)):
             start, stop = self._obj.getbounds()
             if not (start <= i < stop):
+                if isinstance(i, slice):
+                    raise TypeError("array slicing not supported")
                 raise IndexError("array index out of bounds")
             o = self._obj.getitem(i)
             return _expose(o, self._solid)
@@ -986,6 +988,8 @@
                                     "   got %r" % (self._T, T1, T2))
             start, stop = self._obj.getbounds()
             if not (start <= i < stop):
+                if isinstance(i, slice):
+                    raise TypeError("array slicing not supported")
                 raise IndexError("array index out of bounds")
             self._obj.setitem(i, val)
             return

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Wed Aug 23 18:47:27 2006
@@ -779,11 +779,6 @@
         return outof_cobject(v, r_to, llops)
 
 # ____________________________________________________________
-
-def ll_both_none(ins1, ins2):
-    return not ins1 and not ins2
-
-# ____________________________________________________________
 #
 #  Low-level implementation of operations on classes and instances
 
@@ -836,3 +831,26 @@
     else:
         # type(None) -> NULL  (for now)
         return nullptr(typeOf(obj).TO.typeptr.TO)
+
+def ll_both_none(ins1, ins2):
+    return not ins1 and not ins2
+
+# ____________________________________________________________
+
+_missing = object()
+
+def fishllattr(inst, name, default=_missing):
+    p = widest = lltype.normalizeptr(inst)
+    while True:
+        try:
+            return getattr(p, 'inst_' + name)
+        except AttributeError:
+            pass
+        try:
+            p = p.super
+        except AttributeError:
+            break
+    if default is _missing:
+        raise AttributeError("%s has no field %s" % (lltype.typeOf(widest),
+                                                     name))
+    return default

Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py	Wed Aug 23 18:47:27 2006
@@ -122,7 +122,7 @@
             c_LIST    = llops.genvoidconst(LIST)
             return llops.genop('direct_call',
                                [c_newlist, c_LIST, c_len],
-                               LISTPTR)
+                               llops.constTYPE(LISTPTR))
 
         def build_setitem(llops, v_list, index, v_item):
             c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr)

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Wed Aug 23 18:47:27 2006
@@ -897,6 +897,9 @@
     def genvoidconst(self, placeholder):
         return inputconst(Void, placeholder)
 
+    def constTYPE(self, T):
+        return T
+
 # _______________________________________________________________________
 # this has the side-effect of registering the unary and binary operations
 # and the rtyper_chooserepr() methods

Modified: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rpbc.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py	Wed Aug 23 18:47:27 2006
@@ -428,6 +428,21 @@
         res = self.interpret(f1, [2])
         assert res == 6
 
+    def test_call_memo_with_string(self):
+        def memofn(s):
+            return eval(s)
+        memofn._annspecialcase_ = "specialize:memo"
+
+        def f1(i):
+            if i == 1:
+                return memofn("6*7")
+            else:
+                return memofn("1+2+3+4")
+        res = self.interpret(f1, [1])
+        assert res == 42
+        res = self.interpret(f1, [2])
+        assert res == 10
+
     def test_rpbc_bound_method_static_call(self):
         class R:
             def meth(self):



More information about the Pypy-commit mailing list