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

arigo at codespeak.net arigo at codespeak.net
Sat Sep 2 20:30:43 CEST 2006


Author: arigo
Date: Sat Sep  2 20:30:29 2006
New Revision: 31954

Modified:
   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/codegen/llgraph/test/test_llimpl.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/llabstractinterp/test/test_jit_tl.py
   pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py
   pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py
   pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py
   pypy/dist/pypy/jit/llabstractinterp/vlist.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/vlist.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
Log:
(pedronis, arigo)

Improved the interface of RGenOp.  Now it starts to make sense for real
back-ends, and not to make sense any more for producing llgraphs.
Good trade-off.



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	Sat Sep  2 20:30:29 2006
@@ -30,11 +30,6 @@
         return 'var@%d' % (self.stackpos,)
 
 
-class TypeConst(GenConst):
-
-    def __init__(self, kind):
-        self.kind = kind
-
 ##class Const(GenConst):
 
 ##    def revealconst(self, TYPE):
@@ -124,31 +119,80 @@
         self.fixedposition = True
         return self.startaddr
 
-    def geninputarg(self, gv_TYPE):
+    def geninputarg(self, kind):
         res = Var(self.argcount)
         self.argcount += 1
         self.stackdepth += 1
         return res
 
     @specialize.arg(1)
-    def genop(self, opname, args_gv, gv_RESTYPE=None):
+    def genop1(self, opname, gv_arg):
         genmethod = getattr(self, 'op_' + opname)
-        return genmethod(args_gv, gv_RESTYPE)
+        return genmethod(gv_arg)
+
+    @specialize.arg(1)
+    def genop2(self, opname, gv_arg1, gv_arg2):
+        genmethod = getattr(self, 'op_' + opname)
+        return genmethod(gv_arg1, gv_arg2)
 
     def genop_getfield(self, offset, gv_ptr):
-        return self.emit_getfield(gv_ptr, offset)
+        # XXX only for int fields
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        return self.returnvar(mem(edx, offset))
 
     def genop_setfield(self, offset, gv_ptr, gv_value):
-        return self.emit_setfield(gv_ptr, offset, gv_value)
+        # XXX only for ints for now.
+        self.mc.MOV(eax, gv_value.operand(self))
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        self.mc.MOV(mem(edx, offset), eax)
 
     def genop_getsubstruct(self, offset, gv_ptr):
-        return self.emit_getsubstruct(gv_ptr, offset)
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        self.mc.LEA(eax, mem(edx, offset))
+        return self.returnvar(eax)
 
     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
-        return self.emit_getarrayitem(gv_ptr, arraytoken, gv_index)
+        # XXX! only works for GcArray(Signed) for now!!
+        lengthoffset, startoffset, itemoffset = arraytoken
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        if isinstance(gv_index, IntConst):
+            startoffset += itemoffset * gv_index.value
+            op = mem(edx, startoffset)
+        elif itemoffset in SIZE2SHIFT:
+            self.mc.MOV(ecx, gv_index.operand(self))
+            op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset)
+        else:
+            self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset))
+            op = memSIB(edx, ecx, 0, startoffset)
+        return self.returnvar(op)
+
+    def genop_getarraysize(self, arraytoken, gv_ptr):
+        lengthoffset, startoffset, itemoffset = arraytoken
+        self.mc.MOV(edx, gv_ptr.operand(self))
+        return self.returnvar(mem(edx, lengthoffset))
 
     def genop_malloc_fixedsize(self, size):
-        return self.emit_malloc_fixedsize(size)
+        # XXX boehm only, no atomic/non atomic distinction for now
+        self.push(imm(size))
+        gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc)
+        self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr)))
+        return self.returnvar(eax)
+
+    def genop_call(self, sigtoken, gv_fnptr, args_gv):
+        for i in range(len(args_gv)-1, -1, -1):
+            gv_arg = args_gv[i]
+            if gv_arg is not None:
+                self.push(gv_arg.operand(self))
+        target = gv_fnptr.revealconst(lltype.Signed)
+        self.mc.CALL(rel32(target))
+        # XXX only for int return_kind
+        return self.returnvar(eax)
+
+    def genop_same_as(self, kind, gv_x):
+        if gv_x.is_const:    # must always return a var
+            return self.returnvar(gv_x.operand(self))
+        else:
+            return gv_x
 
     def close1(self):
         return Link(self)
@@ -161,6 +205,8 @@
         self.mc.JE(rel32(false_block.getstartaddr()))
         return Link(false_block), Link(self)
 
+    # ____________________________________________________________
+
     def stack_access(self, stackpos):
         return mem(esp, WORD * (self.stackdepth-1 - stackpos))
 
@@ -173,172 +219,114 @@
         self.push(op)
         return res
 
-    def op_int_is_true(self, (gv_x,), gv_RESTYPE):
+    def op_int_is_true(self, gv_x):
         return gv_x
 
-    def op_int_add(self, (gv_x, gv_y), gv_RESTYPE):
-        if isinstance(gv_x, IntConst) and isinstance(gv_y, IntConst):
-            # XXX do this for the other operations too
-            return IntConst(gv_x.value + gv_y.value)
+    def op_int_add(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.ADD(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_sub(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_sub(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.SUB(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_mul(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_mul(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.IMUL(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_floordiv(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_floordiv(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CDQ()
         self.mc.MOV(ecx, gv_y.operand(self))
         self.mc.IDIV(ecx)
         return self.returnvar(eax)
 
-    def op_int_and(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_and(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.AND(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_or(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_or(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.OR(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_xor(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_xor(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.XOR(eax, gv_y.operand(self))
         return self.returnvar(eax)
 
-    def op_int_lt(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_lt(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETL(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_le(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_le(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETLE(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_eq(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_eq(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETE(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_ne(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_ne(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETNE(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_gt(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_gt(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETG(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_ge(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_ge(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.CMP(eax, gv_y.operand(self))
         self.mc.SETGE(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_int_neg(self, (gv_x,), gv_RESTYPE):
+    def op_int_neg(self, gv_x):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.NEG(eax)
         return self.returnvar(eax)
 
-    def op_int_lshift(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_lshift(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.MOV(ecx, gv_y.operand(self))
         self.mc.SHL(eax, cl)
         return self.returnvar(eax)
 
-    def op_int_rshift(self, (gv_x, gv_y), gv_RESTYPE):
+    def op_int_rshift(self, gv_x, gv_y):
         self.mc.MOV(eax, gv_x.operand(self))
         self.mc.MOV(ecx, gv_y.operand(self))
         self.mc.SHR(eax, cl)
         return self.returnvar(eax)
 
-    def op_bool_not(self, (gv_x,), gv_RESTYPE):
-        if isinstance(gv_x, IntConst):
-            return IntConst(not gv_x.value)
+    def op_bool_not(self, gv_x):
         self.mc.CMP(gv_x.operand(self), imm8(0))
         self.mc.SETE(al)
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_cast_pointer(self, (gv_x,), gv_RESTYPE):
-        return gv_x
-
-    def op_same_as(self, (gv_x,), gv_RESTYPE):
-        if gv_x.is_const:    # must always return a var
-            return self.returnvar(gv_x.operand(self))
-        else:
-            return gv_x
-
-    def emit_malloc_fixedsize(self, size):
-        # XXX boehm only, no atomic/non atomic distinction for now
-        self.push(imm(size))
-        gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc)
-        self.mc.CALL(rel32(lltype.cast_ptr_to_int(gc_malloc_ptr)))
-        return self.returnvar(eax)
-
-    def emit_getfield(self, gv_ptr, offset):
-        # XXX only for int fields
-        self.mc.MOV(edx, gv_ptr.operand(self))
-        return self.returnvar(mem(edx, offset))
-
-    def emit_setfield(self, gv_ptr, offset, gv_value):
-        # XXX only for ints for now.
-        self.mc.MOV(eax, gv_value.operand(self))
-        self.mc.MOV(edx, gv_ptr.operand(self))
-        self.mc.MOV(mem(edx, offset), eax)
-
-    def emit_getsubstruct(self, gv_ptr, offset):
-        self.mc.MOV(edx, gv_ptr.operand(self))
-        self.mc.LEA(eax, mem(edx, offset))
-        return self.returnvar(eax)
-
-    def emit_getarrayitem(self, gv_ptr, arraytoken, gv_index):
-        # XXX! only works for GcArray(Signed) for now!!
-        lengthoffset, startoffset, itemoffset = arraytoken
-        self.mc.MOV(edx, gv_ptr.operand(self))
-        if isinstance(gv_index, IntConst):
-            startoffset += itemoffset * gv_index.value
-            op = mem(edx, startoffset)
-        elif itemoffset in SIZE2SHIFT:
-            self.mc.MOV(ecx, gv_index.operand(self))
-            op = memSIB(edx, ecx, SIZE2SHIFT[itemoffset], startoffset)
-        else:
-            self.mc.IMUL(ecx, gv_index.operand(self), imm(itemoffset))
-            op = memSIB(edx, ecx, 0, startoffset)
-        return self.returnvar(op)
-
-    def op_getarraysize(self, (gv_ptr,), gv_RESTYPE):
-        # XXX! only works for GcArray(Signed) for now!!
-        A = DUMMY_A
-        lengthoffset, startoffset, itemoffset = self.rgenop.arrayToken(A)
-        self.mc.MOV(edx, gv_ptr.operand(self))
-        return self.returnvar(mem(edx, lengthoffset))
-
     def op_setarrayitem(self, (gv_ptr, gv_index, gv_value), gv_RESTYPE):
         # XXX! only works for GcArray(Signed) for now!!
+        XXX-fixme
         A = DUMMY_A
         lengthoffset, startoffset, itemoffset = self.rgenop.arrayToken(A)
         self.mc.MOV(eax, gv_value.operand(self))
@@ -354,17 +342,6 @@
             op = memSIB(edx, ecx, 0, startoffset)
         self.mc.MOV(op, eax)
 
-    def op_direct_call(self, args_gv, result_kind):
-        for i in range(len(args_gv)-1, 0, -1):
-            gv_arg = args_gv[i]
-            if gv_arg is not None:
-                self.push(gv_arg.operand(self))
-        gv_fnptr = args_gv[0]
-        target = gv_fnptr.revealconst(lltype.Signed)
-        self.mc.CALL(rel32(target))
-        # XXX only for int return_kind
-        return self.returnvar(eax)
-
 
 DUMMY_A = lltype.GcArray(lltype.Signed)
 SIZE2SHIFT = {1: 0,
@@ -456,9 +433,6 @@
 
 class RI386GenOp(AbstractRGenOp):
     from pypy.jit.codegen.i386.codebuf import MachineCodeBlock
-    
-    gv_IntWord = TypeConst('IntWord')
-    gv_Void = TypeConst('Void')
 
     def __init__(self):
         self.mcs = []   # machine code blocks where no-one is currently writing
@@ -520,24 +494,18 @@
 
     @staticmethod
     @specialize.memo()
-    def kindToken(T): # xxx simplify
-        if T is lltype.Void:
-            return RI386GenOp.gv_Void
-        else:
-            return RI386GenOp.gv_IntWord   # XXX for now
-
-
-    constPrebuiltGlobal = genconst
-
-    constTYPE = kindToken
+    def kindToken(T):
+        return None     # for now
 
     @staticmethod
     @specialize.memo()
-    def constFieldName(T, name):
-        return IntConst(llmemory.offsetof(T, name))
+    def sigToken(FUNCTYPE):
+        return None     # for now
+
+    constPrebuiltGlobal = genconst
 
 
-    def gencallableconst(self, name, block, gv_FUNCTYPE):
+    def gencallableconst(self, sigtoken, name, block):
         prologue = self.newblock()
         #prologue.mc.BREAKPOINT()
         # re-push the arguments so that they are after the return value

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	Sat Sep  2 20:30:29 2006
@@ -15,17 +15,15 @@
 
 def make_adder(rgenop, n):
     # 'return x+n'
-    gv_SIGNED = rgenop.constTYPE(lltype.Signed)
+    signed_kind = rgenop.kindToken(lltype.Signed)
     block = rgenop.newblock()
-    gv_x = block.geninputarg(gv_SIGNED)
-    args_gv = [gv_x,
-               rgenop.genconst(n)]
-    gv_result = block.genop("int_add", args_gv, gv_SIGNED)
+    gv_x = block.geninputarg(signed_kind)
+    gv_result = block.genop2("int_add", gv_x, rgenop.genconst(n))
     link = block.close1()
     link.closereturn(gv_result)
 
-    gv_FUNC = rgenop.constTYPE(FUNC)
-    gv_add_one = rgenop.gencallableconst("adder", block, gv_FUNC)
+    sigtoken = rgenop.sigToken(FUNC)
+    gv_add_one = rgenop.gencallableconst(sigtoken, "adder", block)
     return gv_add_one
 
 def runner(x, y):
@@ -63,29 +61,26 @@
 
 def make_dummy(rgenop):
     # 'return x - (y - (x-1))'
-    gv_SIGNED = rgenop.constTYPE(lltype.Signed)
+    signed_kind = rgenop.kindToken(lltype.Signed)
     block = rgenop.newblock()
-    gv_x = block.geninputarg(gv_SIGNED)
-    gv_y = block.geninputarg(gv_SIGNED)
-    args_gv = [gv_x, rgenop.genconst(1)]
-    gv_z = block.genop("int_sub", args_gv, gv_SIGNED)
+    gv_x = block.geninputarg(signed_kind)
+    gv_y = block.geninputarg(signed_kind)
+    gv_z = block.genop2("int_sub", gv_x, rgenop.genconst(1))
     link = block.close1()
 
     block2 = rgenop.newblock()
-    gv_y2 = block2.geninputarg(gv_SIGNED)
-    gv_z2 = block2.geninputarg(gv_SIGNED)
-    gv_x2 = block2.geninputarg(gv_SIGNED)
+    gv_y2 = block2.geninputarg(signed_kind)
+    gv_z2 = block2.geninputarg(signed_kind)
+    gv_x2 = block2.geninputarg(signed_kind)
     link.close([gv_y, gv_z, gv_x], block2)
 
-    args_gv = [gv_y2, gv_z2]
-    gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
-    args_gv = [gv_x2, gv_s2]
-    gv_t2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+    gv_s2 = block2.genop2("int_sub", gv_y2, gv_z2)
+    gv_t2 = block2.genop2("int_sub", gv_x2, gv_s2)
     link2 = block2.close1()
 
     link2.closereturn(gv_t2)
-    gv_FUNC2 = rgenop.constTYPE(FUNC2)
-    gv_dummyfn = rgenop.gencallableconst("dummy", block, gv_FUNC2)
+    sigtoken = rgenop.sigToken(FUNC2)
+    gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", block)
     return gv_dummyfn
 
 def dummy_runner(x, y):
@@ -122,30 +117,28 @@
 def make_branching(rgenop):
     # 'if x > 5: return x-1
     #  else:     return y'
-    gv_SIGNED = rgenop.constTYPE(lltype.Signed)
-    gv_BOOL   = rgenop.constTYPE(lltype.Bool)
+    signed_kind = rgenop.kindToken(lltype.Signed)
     block = rgenop.newblock()
-    gv_x = block.geninputarg(gv_SIGNED)
-    gv_y = block.geninputarg(gv_SIGNED)
-    args_gv = [gv_x, rgenop.genconst(5)]
-    gv_cond = block.genop("int_gt", args_gv, gv_BOOL)
+    gv_x = block.geninputarg(signed_kind)
+    gv_y = block.geninputarg(signed_kind)
+    gv_cond = block.genop2("int_gt", gv_x, rgenop.genconst(5))
     link_false, link_true = block.close2(gv_cond)
 
     block2 = rgenop.newblock()
-    gv_one = block2.geninputarg(gv_SIGNED)
-    gv_x2 = block2.geninputarg(gv_SIGNED)
-    gv_y2 = block2.geninputarg(gv_SIGNED)
+    gv_one = block2.geninputarg(signed_kind)
+    gv_x2 = block2.geninputarg(signed_kind)
+    gv_y2 = block2.geninputarg(signed_kind)
     link_true.close([rgenop.genconst(1), gv_x, gv_y], block2)
 
-    args_gv = [gv_x2, gv_one]
-    gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+    gv_s2 = block2.genop2("int_sub", gv_x2, gv_one)
     link2 = block2.close1()
     link2.closereturn(gv_s2)
 
     link_false.closereturn(gv_y)
 
-    gv_FUNC2 = rgenop.constTYPE(FUNC2)
-    gv_branchingfn = rgenop.gencallableconst("branching", block, gv_FUNC2)
+    sigtoken = rgenop.sigToken(FUNC2)
+    gv_branchingfn = rgenop.gencallableconst(sigtoken,
+                                             "branching", block)
     return gv_branchingfn
 
 def branching_runner(x, y):

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	Sat Sep  2 20:30:29 2006
@@ -13,6 +13,7 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.lltypesystem.rclass import fishllattr
+from pypy.rpython.lltypesystem.lloperation import llop
 
 
 # for debugging, sanity checks in non-RPython code
@@ -96,17 +97,34 @@
         opname = LLSupport.from_rstr(opname)
     block = from_opaque_object(blockcontainer.obj)
     assert block.exits == [], "block already closed"
-    if isinstance(gv_RESULT_TYPE, lltype.LowLevelType):
+    opvars = _inputvars(vars_gv)
+    if gv_RESULT_TYPE is guess:
+        RESULT_TYPE = guess_result_type(opname, opvars)
+    elif isinstance(gv_RESULT_TYPE, lltype.LowLevelType):
         RESULT_TYPE = gv_RESULT_TYPE
     else:
         RESULT_TYPE = from_opaque_object(gv_RESULT_TYPE).value
-    opvars = _inputvars(vars_gv)
     v = flowmodel.Variable()
     v.concretetype = RESULT_TYPE
     op = flowmodel.SpaceOperation(opname, opvars, v)
     block.operations.append(op)
     return to_opaque_object(erasedvar(v, block))
 
+def guess_result_type(opname, opvars):
+    op = getattr(llop, opname)
+    need_result_type = getattr(op.fold, 'need_result_type', False)
+    assert not need_result_type, ("cannot guess the result type of %r"
+                                  % (opname,))
+    examples = []
+    for v in opvars:
+        example = v.concretetype._example()
+        if isinstance(v.concretetype, lltype.Primitive):
+            if example == 0:
+                example = type(example)(1)     # to avoid ZeroDivisionError
+        examples.append(example)
+    result = op.fold(*examples)
+    return lltype.typeOf(result)
+
 def gencallableconst(name, targetcontainer, gv_FUNCTYPE):
     # 'name' is just a way to track things
     if not isinstance(name, str):
@@ -327,7 +345,8 @@
 nulllink = lltype.nullptr(LINK.TO)
 gv_Void = constTYPE(lltype.Void)
 
-dummy_placeholder = placeholder("dummy")
+dummy_placeholder = placeholder(None)
+guess = placeholder('guess')
 
 
 # helpers
@@ -384,4 +403,4 @@
 # XXX(for now) void constant constructors
 setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True)
 setannotation(constTYPE,      s_ConstOrVar, specialize_as_constant=True)
-setannotation(placeholder,    s_ConstOrVar, specialize_as_constant=True)
+#setannotation(placeholder,    s_ConstOrVar, specialize_as_constant=True)

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	Sat Sep  2 20:30:29 2006
@@ -26,6 +26,7 @@
         return repr(RGenOp.reveal(self))
 
 gv_Void = LLConst(llimpl.constTYPE(lltype.Void))
+gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder)
 
 
 class LLBlock(CodeGenBlock):
@@ -35,10 +36,29 @@
     def geninputarg(self, gv_TYPE):
         return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v))
 
+##    @specialize.arg(1)
+##    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))
+
+    @specialize.arg(1)
+    def genop1(self, opname, gv_arg):
+        return LLVar(llimpl.genop(self.b, opname, [gv_arg], llimpl.guess))
+
     @specialize.arg(1)
-    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))
+    def genop2(self, opname, gv_arg1, gv_arg2):
+        return LLVar(llimpl.genop(self.b, opname, [gv_arg1, gv_arg2],
+                                  llimpl.guess))
+
+    def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv):
+        vars_gv = [gv_callable]
+        for i in range(len(ARGS_gv)):
+            gv_arg = args_gv[i]
+            if gv_arg is not None:
+                gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, gv_arg.v))
+            vars_gv.append(gv_arg)
+        # XXX indirect_call later
+        return LLVar(llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v))
 
     def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr):
         vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v]
@@ -63,11 +83,23 @@
         return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv,
                                   gv_ITEMTYPE.v))
 
+    def genop_getarraysize(self, gv_ITEMTYPE, gv_ptr):
+        return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v],
+                                  llimpl.constTYPE(lltype.Signed)))
+
     def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)):
         vars_gv = [gv_TYPE.v]
         return LLVar(llimpl.genop(self.b, 'malloc', vars_gv,
                                   gv_PTRTYPE.v))
-                                  
+
+    def genop_malloc_varsize(self, (gv_TYPE, gv_PTRTYPE), gv_length):
+        vars_gv = [gv_TYPE.v, gv_length.v]
+        return LLVar(llimpl.genop(self.b, 'malloc_varsize', vars_gv,
+                                  gv_PTRTYPE.v))
+
+    def genop_same_as(self, gv_TYPE, gv_value):
+        return LLVar(gv_value.v)
+
     def close1(self):
         return LLLink(llimpl.closeblock1(self.b))
 
@@ -84,7 +116,8 @@
         llimpl.closelink(self.l, vars_gv, targetblock.b)
 
     def closereturn(self, gv_returnvar):
-        llimpl.closereturnlink(self.l, gv_returnvar.v)
+        llimpl.closereturnlink(self.l,
+                               (gv_returnvar or gv_dummy_placeholder).v)
 
 
 class RGenOp(AbstractRGenOp):
@@ -94,7 +127,8 @@
         return LLBlock(llimpl.newblock())
 
     # XXX what kind of type/kind information does this need?
-    def gencallableconst(self, name, targetblock, gv_FUNCTYPE):
+    def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name,
+                         targetblock):
         return LLConst(llimpl.gencallableconst(name, targetblock.b,
                                                gv_FUNCTYPE.v))
 
@@ -130,22 +164,12 @@
     def arrayToken(A):
         return LLConst(llimpl.constTYPE(A.OF))
 
-
     @staticmethod
     @specialize.memo()
-    def constTYPE(T):
-        return LLConst(llimpl.constTYPE(T))
-
-    @staticmethod
-    @specialize.arg(0)
-    def placeholder(dummy):
-        return LLConst(llimpl.placeholder(dummy))
-
-    @staticmethod
-    @specialize.memo()
-    def constFieldName(T, name):
-        assert name in T._flds
-        return LLConst(llimpl.constFieldName(name))
+    def sigToken(FUNCTYPE):
+        return ([LLConst(llimpl.constTYPE(A)) for A in FUNCTYPE.ARGS],
+                LLConst(llimpl.constTYPE(FUNCTYPE.RESULT)),
+                LLConst(llimpl.constTYPE(FUNCTYPE)))
 
     constPrebuiltGlobal = genconst
 

Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py	Sat Sep  2 20:30:29 2006
@@ -135,14 +135,6 @@
     assert c.concretetype == lltype.Void
     assert c.value == lltype.Signed
 
-    def dummy():
-        return placeholder(None)
-    res = interpret(dummy, [])
-    c = from_opaque_object(res)
-    assert isinstance(c, flowmodel.Constant)
-    assert c.concretetype == lltype.Void
-    assert c.value == None
-
 def test_rtype_revealcosnt():
     def hide_and_reveal(v):
         gv = genconst(v)

Modified: pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py	Sat Sep  2 20:30:29 2006
@@ -160,7 +160,8 @@
 
 class LLAbstractInterp(object):
 
-    def __init__(self, policy=best_policy):
+    def __init__(self, rtyper, policy=best_policy):
+        self.rtyper = rtyper
         self.graphs = []
         self.graphstates = {}     # {origgraph: {BlockState: GraphState}}
         self.blocks = {}          # {BlockState.key(): list-of-LLBlockStates}
@@ -276,8 +277,11 @@
             assert isinstance(v2, (AVariable, AConstant))
             if isinstance(v2, AConstant):
                 # sanity check violating encapsulation
-                v1 = rgenop.reveal(v1)
-                assert v1.value == v2.value
+                if v2.concretetype is lltype.Void:
+                    assert v1 is None
+                else:
+                    v1 = rgenop.reveal(v1)
+                    assert v1.value == v2.value
             else:
                 args.append(v1)
         self.link.close(args, block)
@@ -541,18 +545,36 @@
             ls.link = cases[ls.exitcase]
         return b
 
-    def genop(self, opname, args, RESULT_TYPE=lltype.Void):
-        return self.newblock.genop(opname, args,
-                                   rgenop.constTYPE(RESULT_TYPE))
+##    def genop(self, opname, args, RESULT_TYPE=lltype.Void):
+##        return self.newblock.genop(opname, args,
+##                                   rgenop.constTYPE(RESULT_TYPE))
 
-    def genconst(self, llvalue):
-        return rgenop.genconst(llvalue)
+    def genop1(self, opname, arg):
+        return self.newblock.genop1(opname, arg)
+
+    def genop2(self, opname, arg1, arg2):
+        return self.newblock.genop2(opname, arg1, arg2)
+
+    def genop_call(self, sigtoken, v_callable, args_v):
+        return self.newblock.genop_call(sigtoken, v_callable, args_v)
+
+    def genop_malloc_fixedsize(self, alloctoken):
+        return self.newblock.genop_malloc_fixedsize(alloctoken)
 
-    def genvoidconst(self, placeholder):
-        return rgenop.placeholder(placeholder)
+    def genop_malloc_varsize(self, alloctoken, v_length):
+        return self.newblock.genop_malloc_varsize(alloctoken, v_length)
 
-    def constTYPE(self, T):
-        return T
+    def genop_getfield(self, fieldtoken, v_ptr):
+        return self.newblock.genop_getfield(fieldtoken, v_ptr)
+
+    def genop_setfield(self, fieldtoken, v_ptr, v_value):
+        return self.newblock.genop_setfield(fieldtoken, v_ptr, v_value)
+
+    def genop_getsubstruct(self, fieldtoken, v_ptr):
+        return self.newblock.genop_getsubstruct(fieldtoken, v_ptr)
+
+    def genconst(self, llvalue):
+        return rgenop.genconst(llvalue)
     
     def binding(self, v):
         assert isinstance(v, (Constant, Variable))
@@ -595,20 +617,27 @@
         return a_result
 
     def residual(self, op, args_a):
-        T= op.result.concretetype
-        retvar = self.genop(op.opname,
-                              [a.forcegenvarorconst(self) for a in args_a],
-                              T)
+        T = op.result.concretetype
+        args_v = [a.forcegenvarorconst(self) for a in args_a]
+        if op.opname == 'direct_call':
+            sigtoken = rgenop.sigToken(args_a[0].getconcretetype().TO)
+            retvar = self.genop_call(sigtoken, args_v[0], args_v[1:])
+        elif op.opname == 'getfield':
+            fieldtoken = rgenop.fieldToken(args_a[0].getconcretetype().TO,
+                                           op.args[1].value)
+            retvar = self.genop_getfield(fieldtoken, args_v[0])
+        else:
+            # generic version
+            genopmeth = getattr(self, 'genop%d' % len(args_a))
+            retvar = genopmeth(op.opname, *args_v)
         return LLAbstractValue(AVariable(T, genvar=retvar))
 
     def residual_direct_call(self, FUNCTYPE, name, target, args_a):
         T = FUNCTYPE.RESULT
-        gen_fn_const = rgenop.gencallableconst(name,
-                                               target,
-                                               rgenop.constTYPE(FUNCTYPE))
-        retvar = self.genop('direct_call', [gen_fn_const] +
-                              [a.forcegenvarorconst(self) for a in args_a],
-                              T)
+        sigtoken = rgenop.sigToken(FUNCTYPE)
+        gen_fn_const = rgenop.gencallableconst(sigtoken, name, target)
+        retvar = self.genop_call(sigtoken, gen_fn_const,
+                                 [a.forcegenvarorconst(self) for a in args_a])
         return LLAbstractValue(AVariable(T, genvar=retvar))
         
     

Modified: pypy/dist/pypy/jit/llabstractinterp/llcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llcontainer.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llcontainer.py	Sat Sep  2 20:30:29 2006
@@ -52,19 +52,16 @@
         RESULT_TYPE = lltype.Ptr(self.T)
         if self.a_parent is not None:
             PARENT_TYPE = self.a_parent.getconcretetype().TO
-            parentindex = rgenop.constFieldName(PARENT_TYPE, self.parentindex)
+            fieldtoken = rgenop.fieldToken(PARENT_TYPE, self.parentindex)
             v_parent = self.a_parent.forcegenvarorconst(builder)
-            v_result = builder.genop('getsubstruct',
-                                     [v_parent, parentindex], RESULT_TYPE)
+            v_result = builder.genop_getsubstruct(fieldtoken, v_parent)
         else:
-            t = rgenop.constTYPE(self.T)
+            t = rgenop.allocToken(self.T)
             if self.T._is_varsize():
-                v_result = builder.genop('malloc_varsize',
-                                         [t,
-                                          builder.genconst(self.length)],
-                                         RESULT_TYPE)
+                c_length = builder.genconst(self.length)
+                v_result = builder.genop_malloc_varsize(t, c_length)
             else:
-                v_result = builder.genop('malloc', [t], RESULT_TYPE)
+                v_result = builder.genop_malloc_fixedsize(t)
             self.buildcontent(builder, v_result)
         return v_result
 
@@ -76,10 +73,8 @@
                 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, c_name],
-                                             lltype.Ptr(T))
+                    fieldtoken = rgenop.fieldToken(self.T, name)
+                    v_subptr = builder.genop_getsubstruct(fieldtoken, v_target)
                     assert isinstance(a_value.content, LLVirtualContainer)
                     a_value.content.buildcontent(builder, v_subptr)
                 else:
@@ -167,9 +162,8 @@
         return getattr(self.T, name)
 
     def setop(self, builder, v_target, name, v_value):
-        c_name = rgenop.constFieldName(self.T, name)
-        builder.genop('setfield', [v_target, c_name, v_value],
-                      lltype.Void)
+        fieldtoken = rgenop.fieldToken(self.T, name)
+        builder.genop_setfield(fieldtoken, v_target, v_value)
 
 
 class LLVirtualArray(LLVirtualContainer):

Modified: pypy/dist/pypy/jit/llabstractinterp/llvalue.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llvalue.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llvalue.py	Sat Sep  2 20:30:29 2006
@@ -16,11 +16,9 @@
         Hashable.__init__(self, value)   
         self.concretetype = T or lltype.typeOf(value)
         self.genvar = genvar
-        if T is lltype.Void and self.genvar is None:
-            self.genvar = rgenop.placeholder(value)
-        
+
     def getgenvar(self, builder):
-        if self.genvar is None:
+        if self.genvar is None and self.concretetype is not lltype.Void:
             self.genvar = builder.genconst(self.value)
         return self.genvar
 
@@ -202,7 +200,7 @@
             assert c.concretetype == self.concretetype
             result = LLAbstractValue(c)
         else:
-            gen_v = block.geninputarg(rgenop.constTYPE(self.concretetype))
+            gen_v = block.geninputarg(rgenop.kindToken(self.concretetype))
             result = LLAbstractValue(AVariable(self.concretetype, genvar=gen_v))
         result.origin.append(self)
         return result

Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	Sat Sep  2 20:30:29 2006
@@ -17,11 +17,12 @@
     #inline.auto_inlining(t, 0.3)
     
     mod.graph1 = t.graphs[0]
+    mod.rtyper = rtyper
     mod.llinterp = LLInterpreter(rtyper)
     
 
 def jit_tl(code):
-    interp = LLAbstractInterp()
+    interp = LLAbstractInterp(rtyper)
     hints = {0: string_repr.convert_const(code),
              1: 0}
     graph2 = interp.eval(graph1, hints)

Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tlr.py	Sat Sep  2 20:30:29 2006
@@ -15,7 +15,7 @@
     rtyper = t.buildrtyper()
     rtyper.specialize()
 
-    interp = LLAbstractInterp()
+    interp = LLAbstractInterp(rtyper)
     hints = {0: string_repr.convert_const(tlr.SQUARE)}
     graph2 = interp.eval(t.graphs[0], hints)
     #graph2.show()

Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_llabstractinterp.py	Sat Sep  2 20:30:29 2006
@@ -34,7 +34,7 @@
     rtyper = t.buildrtyper()
     rtyper.specialize()
     # build the residual ll graphs by propagating the hints
-    interp = LLAbstractInterp(policy)
+    interp = LLAbstractInterp(rtyper, policy)
     hints = {}
     for hint in arghints:
         hints[hint] = argvalues[hint]

Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_vlist.py	Sat Sep  2 20:30:29 2006
@@ -16,7 +16,7 @@
     rtyper.specialize()
     graph1 = t.graphs[0]
 
-    interp = LLAbstractInterp(policy)
+    interp = LLAbstractInterp(rtyper, policy)
     hints = {}
     llvalues = []
     for i, value in enumerate(argvalues):

Modified: pypy/dist/pypy/jit/llabstractinterp/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/vlist.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/vlist.py	Sat Sep  2 20:30:29 2006
@@ -3,6 +3,7 @@
 from pypy.jit.llabstractinterp.llvalue import LLAbstractValue, AConstant
 from pypy.jit.llabstractinterp.llvalue import ll_dummy_value
 from pypy.jit.llabstractinterp.llcontainer import LLAbstractContainer
+from pypy.jit.codegen.llgraph.rgenop import rgenop
 
 
 class LLVirtualList(LLAbstractContainer):
@@ -40,9 +41,29 @@
         return LLVirtualList(self.T, items_a)
 
     def build_runtime_container(self, builder):
+        rtyper = builder.interp.rtyper
+        LIST = self.T
+
+        argtypes = [lltype.Signed]
+        ll_newlist_ptr = rtyper.annotate_helper_fn(LIST.ll_newlist,
+                                                   argtypes)
+        c_ll_newlist = rgenop.constPrebuiltGlobal(ll_newlist_ptr)
+        ll_newlist_sig = rgenop.sigToken(lltype.typeOf(ll_newlist_ptr).TO)
+
+        argtypes = [lltype.Ptr(LIST), lltype.Signed, LIST.ITEM]
+        ll_setitem_ptr = rtyper.annotate_helper_fn(LIST.ll_setitem_fast,
+                                                   argtypes)
+        c_ll_setitem = rgenop.constPrebuiltGlobal(ll_setitem_ptr)
+        ll_setitem_sig = rgenop.sigToken(lltype.typeOf(ll_setitem_ptr).TO)
+
         items_v = [a.forcegenvarorconst(builder) for a in self.items_a]
-        v_result = self.T.list_builder.build(builder, items_v)
-        return v_result
+        v_list = builder.genop_call(ll_newlist_sig, c_ll_newlist,
+                                    [None, builder.genconst(len(items_v))])
+
+        for i in range(len(items_v)):
+            builder.genop_call(ll_setitem_sig, c_ll_setitem,
+                               [v_list, builder.genconst(i), items_v[i]])
+        return v_list
 
     # ____________________________________________________________
     # High-level operations

Modified: pypy/dist/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/oop.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/oop.py	Sat Sep  2 20:30:29 2006
@@ -28,19 +28,20 @@
         self.argpositions = []
         for i, obj in enumerate(self.argtuple):
             if isinstance(obj, Index):
-                self.argpositions.append(obj.n + 1)
+                self.argpositions.append(obj.n)
             else:
-                self.argpositions.append(0)
+                self.argpositions.append(-1)
 
         for i in range(nb_args):
             ARGTYPE = FUNCTYPE.ARGS[i]
-            assert ((i+1) in self.argpositions) == (ARGTYPE is not lltype.Void)
+            assert (i in self.argpositions) == (ARGTYPE is not lltype.Void)
 
         RGenOp = hrtyper.RGenOp
         self.args_gv = [None] * nb_args
-        self.args_gv.insert(0, RGenOp.constPrebuiltGlobal(fnobj._as_ptr()))
+        self.gv_fnptr = RGenOp.constPrebuiltGlobal(fnobj._as_ptr())
         self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
         self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+        self.sigtoken = RGenOp.sigToken(FUNCTYPE)
 
         if operation_name == 'newlist':
             from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist
@@ -58,10 +59,8 @@
         argpositions = self.argpositions
         for i in range(len(argpositions)):
             pos = argpositions[i]
-            if pos > 0:
+            if pos >= 0:
                 gv_arg = argboxes[i].getgenvar(builder)
                 args_gv[pos] = gv_arg
-        gv_result = builder.genop('direct_call',
-                                  args_gv,
-                                  self.result_kind)
+        gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv)
         return self.redboxbuilder(self.result_kind, gv_result)

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Sat Sep  2 20:30:29 2006
@@ -123,6 +123,7 @@
         assert isinstance(PTRTYPE.TO, lltype.Array)
         FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF)
         self.arraytoken = RGenOp.arrayToken(PTRTYPE.TO)
+        self.indexkind = RGenOp.kindToken(lltype.Signed)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Sat Sep  2 20:30:29 2006
@@ -61,9 +61,8 @@
         arg = rvalue.ll_getvalue(argbox, ARG0)
         res = opdesc.llop(RESULT, arg)
         return rvalue.ll_fromvalue(jitstate, res)
-    op_args = [argbox.getgenvar(jitstate.curbuilder)]
-    genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
-                                      opdesc.result_kind)
+    gv_arg = argbox.getgenvar(jitstate.curbuilder)
+    genvar = jitstate.curbuilder.genop1(opdesc.opname, gv_arg)
     return opdesc.redboxcls(opdesc.result_kind, genvar)
 
 def ll_generate_operation2(opdesc, jitstate, argbox0, argbox1):
@@ -77,10 +76,9 @@
         arg1 = rvalue.ll_getvalue(argbox1, ARG1)
         res = opdesc.llop(RESULT, arg0, arg1)
         return rvalue.ll_fromvalue(jitstate, res)
-    op_args = [argbox0.getgenvar(jitstate.curbuilder),
-               argbox1.getgenvar(jitstate.curbuilder)]
-    genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
-                                       opdesc.result_kind)
+    gv_arg0 = argbox0.getgenvar(jitstate.curbuilder)
+    gv_arg1 = argbox1.getgenvar(jitstate.curbuilder)
+    genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1)
     return opdesc.redboxcls(opdesc.result_kind, genvar)
 
 def ll_generate_getfield(jitstate, fielddesc, argbox):
@@ -128,6 +126,16 @@
                                                     
     return fielddesc.redboxcls(fielddesc.kind, genvar)
 
+def ll_generate_getarraysize(jitstate, fielddesc, argbox):
+    if argbox.is_constant():
+        array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
+        res = len(array)
+        return rvalue.ll_fromvalue(jitstate, res)
+    genvar = jitstate.curbuilder.genop_getarraysize(
+        fielddesc.arraytoken,
+        argbox.getgenvar(jitstate.curbuilder))
+    return rvalue.IntRedBox(fielddesc.indexkind, genvar)
+
 # ____________________________________________________________
 # other jitstate/graph level operations
 
@@ -299,9 +307,20 @@
 ##        return self.rgenop.placeholder(dummy)
 ##    genvoidconst._annspecialcase_ = 'specialize:arg(1)'
 
-    def genop(self, opname, args_gv, result_kind=None):
-        return self.block.genop(opname, args_gv, result_kind)
-    genop._annspecialcase_ = 'specialize:arg(1)'
+##    def genop(self, opname, args_gv, result_kind=None):
+##        return self.block.genop(opname, args_gv, result_kind)
+##    genop._annspecialcase_ = 'specialize:arg(1)'
+
+    def genop1(self, opname, gv_arg):
+        return self.block.genop1(opname, gv_arg)
+    genop1._annspecialcase_ = 'specialize:arg(1)'
+
+    def genop2(self, opname, gv_arg1, gv_arg2):
+        return self.block.genop2(opname, gv_arg1, gv_arg2)
+    genop2._annspecialcase_ = 'specialize:arg(1)'
+
+    def genop_call(self, sigtoken, gv_callable, args_gv):
+        return self.block.genop_call(sigtoken, gv_callable, args_gv)
 
     def genop_getfield(self, fieldtoken, gv_ptr):
         return self.block.genop_getfield(fieldtoken, gv_ptr)
@@ -314,10 +333,16 @@
 
     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
         return self.block.genop_getarrayitem(arraytoken, gv_ptr, gv_index)
+    
+    def genop_getarraysize(self, arraytoken, gv_ptr):
+        return self.block.genop_getarraysize(arraytoken, gv_ptr)
 
     def genop_malloc_fixedsize(self, alloctoken):
         return self.block.genop_malloc_fixedsize(alloctoken)
 
+    def genop_same_as(self, kind, gv_value):
+        return self.block.genop_same_as(kind, gv_value)
+
     def constTYPE(self, T):
         return self.rgenop.constTYPE(T)
     constTYPE._annspecialcase_ = 'specialize:arg(1)'

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Sat Sep  2 20:30:29 2006
@@ -151,11 +151,32 @@
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
-        return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getarrayitem,
+        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    ],
             ts.s_RedBox)
 
+    def translate_op_getarraysize(self, hop):
+        res = self.generic_translate_operation(hop, force=True)
+        if res is not None:
+            return res
+        
+        PTRTYPE = originalconcretetype(hop.args_s[0])
+        ts = self.timeshifter
+        [v_argbox] = hop.inputargs(self.getredrepr(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()
+        return hop.llops.genmixlevelhelpercall(
+            rtimeshift.ll_generate_getarraysize,
+            [ts.s_JITState, s_fielddesc, ts.s_RedBox],
+            [v_jitstate,    c_fielddesc, v_argbox   ],
+            ts.s_RedBox)
+
+
     def translate_op_setfield(self, hop):
         if isinstance(hop.args_r[0], BlueRepr):
             return hop.args_r[0].timeshift_setfield(hop)

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Sat Sep  2 20:30:29 2006
@@ -49,7 +49,7 @@
         if self.is_constant():
             # cannot mutate constant boxes in-place
             box = self.copy(memo)
-            box.genvar = builder.genop("same_as", [self.genvar], self.kind)
+            box.genvar = builder.genop_same_as(self.kind, self.genvar)
             return box
         else:
             # force virtual containers

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	Sat Sep  2 20:30:29 2006
@@ -151,22 +151,22 @@
                     llvalue     = args[1]
                     args = args[2:]
                     TYPE = lltype.typeOf(llvalue)
-                    gv_type = rgenop.constTYPE(TYPE)
+                    kind = rgenop.kindToken(TYPE)
                     boxcls = rvalue.ll_redboxcls(TYPE)
-                    gv_arg = rtimeshift.ll_geninputarg(builder, gv_type)
+                    gv_arg = rtimeshift.ll_geninputarg(builder, kind)
                     if is_constant:
                         # ignore the gv_arg above, which is still present
                         # to give the residual graph a uniform signature
                         gv_arg = rgenop.genconst(llvalue)
-                    box = boxcls(gv_type, gv_arg)
+                    box = boxcls(kind, gv_arg)
                     timeshifted_entrypoint_args += (box,)
             startblock = rtimeshift.ll_end_setup_builder(builder)
             endbuilder = timeshifted_entrypoint(builder, None,
                                               *timeshifted_entrypoint_args)
             endbuilder.finish_and_return()
-            gv_functype = rgenop.constTYPE(FUNC)
-            gv_generated = rgenop.gencallableconst("generated", startblock,
-                                                   gv_functype)
+            sigtoken = rgenop.sigToken(FUNC)
+            gv_generated = rgenop.gencallableconst(sigtoken, "generated",
+                                                   startblock)
             generated = gv_generated.revealconst(lltype.Ptr(FUNC))
             return generated
 

Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py	Sat Sep  2 20:30:29 2006
@@ -17,11 +17,14 @@
         ll_newlist_ptr = rtyper.annotate_helper_fn(LIST.ll_newlist,
                                                    argtypes)
         self.gv_ll_newlist = RGenOp.constPrebuiltGlobal(ll_newlist_ptr)
+        self.tok_ll_newlist = RGenOp.sigToken(lltype.typeOf(ll_newlist_ptr).TO)
 
         argtypes = [self.LISTPTR, lltype.Signed, LIST.ITEM]
         ll_setitem_fast = rtyper.annotate_helper_fn(LIST.ll_setitem_fast,
                                                     argtypes)
         self.gv_ll_setitem_fast = RGenOp.constPrebuiltGlobal(ll_setitem_fast)
+        self.tok_ll_setitem_fast = RGenOp.sigToken(
+            lltype.typeOf(ll_setitem_fast).TO)
 
     def factory(self, length, itembox):
         vlist = VirtualList(self, length, itembox)
@@ -84,15 +87,18 @@
         boxes = self.item_boxes
         self.item_boxes = None
 
-        args_gv = [typedesc.gv_ll_newlist, None, builder.genconst(len(boxes))]
-        gv_list = builder.genop('direct_call', args_gv, typedesc.ptrkind)
+        args_gv = [None, builder.genconst(len(boxes))]
+        gv_list = builder.genop_call(typedesc.tok_ll_newlist,
+                                     typedesc.gv_ll_newlist,
+                                     args_gv)
         self.ownbox.genvar = gv_list
         self.ownbox.content = None
         for i in range(len(boxes)):
             gv_item = boxes[i].getgenvar(builder)
-            args_gv = [typedesc.gv_ll_setitem_fast, gv_list,
-                       builder.genconst(i), gv_item]
-            builder.genop('direct_call', args_gv)
+            args_gv = [gv_list, builder.genconst(i), gv_item]
+            builder.genop_call(typedesc.tok_ll_setitem_fast,
+                               typedesc.gv_ll_setitem_fast,
+                               args_gv)
 
     def freeze(self, memo):
         contmemo = memo.containers

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sat Sep  2 20:30:29 2006
@@ -3,6 +3,7 @@
 """
 
 from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.objspace.flow.model import roproperty
 
 
 class LLOp(object):
@@ -54,7 +55,7 @@
             val = lltype.enforce(RESULTTYPE, val)
         return val
 
-    def fold(self, RESULTTYPE, *args):
+    def get_fold_impl(self):
         global lltype                 #  <- lazy import hack, worth an XXX
         from pypy.rpython.lltypesystem import lltype
         if self.canfold or self.opname in ('getfield', 'getarrayitem'):
@@ -67,8 +68,8 @@
                 raise error
         # cache the implementation function into 'self'
         self.fold = op_impl
-        return self(RESULTTYPE, *args)
-    fold.need_result_type = True
+        return op_impl
+    fold = roproperty(get_fold_impl)
 
 
 def enum_ops_without_sideeffects(raising_is_ok=False):



More information about the Pypy-commit mailing list