[pypy-svn] r54727 - in pypy/branch/oo-jit/pypy/jit/codegen: cli cli/test test

antocuni at codespeak.net antocuni at codespeak.net
Wed May 14 12:31:28 CEST 2008


Author: antocuni
Date: Wed May 14 12:31:27 2008
New Revision: 54727

Modified:
   pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py
   pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py
   pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py
   pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py
   pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py
   pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py
Log:
a big refactoring to cli jit backend; the main Builder is now a
GraphBuilder, which is only a collections of one or more
BranchBuilder; instead of generating code, BranchBuilders store
operations in a list, which are then serialized to CLI bytecode only
at the end.

This solves a couple of problems and make some more tests passing



Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py	Wed May 14 12:31:27 2008
@@ -8,7 +8,7 @@
     def _fmt(self, arg):
         from System.Reflection import Emit, FieldInfo
         if isinstance(arg, Emit.LocalBuilder):
-            return 'v%d' % arg.LocalIndex
+            return 'var%d' % arg.LocalIndex
         elif isinstance(arg, Emit.Label):
             return 'label%d' % self.labels[arg]
         elif isinstance(arg, FieldInfo):

Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py	Wed May 14 12:31:27 2008
@@ -17,7 +17,7 @@
         if self._gv_res is None:
             restype = self.restype()
             if restype is not None:
-                loc = self.builder.il.DeclareLocal(restype)
+                loc = self.builder.parent.il.DeclareLocal(restype)
                 self._gv_res = GenLocalVar(loc)
         return self._gv_res
 
@@ -41,7 +41,7 @@
 
     def emit(self):
         self.pushAllArgs()
-        self.builder.il.Emit(self.getOpCode())
+        self.builder.parent.il.Emit(self.getOpCode())
         self.storeResult()
 
     def getOpCode(self):
@@ -59,7 +59,7 @@
 
     def emit(self):
         self.pushAllArgs()
-        self.builder.il.Emit(self.getOpCode())
+        self.builder.parent.il.Emit(self.getOpCode())
         self.storeResult()
 
     def getOpCode(self):
@@ -82,8 +82,8 @@
         return None
 
     def emit(self):
-        self.builder.il.MarkLabel(self.label)
-
+        self.builder.parent.il.MarkLabel(self.label)
+        
 class FollowLink(Operation):
     
     def __init__(self, builder, outputargs_gv, inputargs_gv, label):
@@ -99,7 +99,8 @@
         for i in range(len(self.outputargs_gv)):
             self.outputargs_gv[i].load(self.builder)
             self.inputargs_gv[i].store(self.builder)
-        self.builder.il.Emit(OpCodes.Br, self.label)
+        self.builder.parent.il.Emit(OpCodes.Br, self.label)
+
 
 class Branch(Operation):
     
@@ -115,7 +116,7 @@
     def emit(self):
         if self.gv_cond is not None:
             self.gv_cond.load(self.builder)
-        self.builder.il.Emit(self.opcode, self.label)
+        self.builder.parent.il.Emit(self.opcode, self.label)
 
 class Return(Operation):
 
@@ -127,9 +128,12 @@
         return None
 
     def emit(self):
+        retvar = self.builder.parent.retvar
+        retlabel = self.builder.parent.retlabel
         if self.gv_x is not None:
             self.gv_x.load(self.builder)
-        self.builder.il.Emit(OpCodes.Ret)
+            self.builder.parent.il.Emit(OpCodes.Stloc, retvar)
+        self.builder.parent.il.Emit(OpCodes.Br, retlabel)
 
 class Call(Operation):
 
@@ -149,10 +153,10 @@
         delegate_type = class2type(self.sigtoken.funcclass)
         meth_invoke = delegate_type.GetMethod('Invoke')
         self.gv_fnptr.load(self.builder)
-        self.builder.il.Emit(OpCodes.Castclass, delegate_type)
+        self.builder.parent.il.Emit(OpCodes.Castclass, delegate_type)
         for gv_arg in self.args_gv:
             gv_arg.load(self.builder)
-        self.builder.il.EmitCall(OpCodes.Callvirt, meth_invoke, None)
+        self.builder.parent.il.EmitCall(OpCodes.Callvirt, meth_invoke, None)
         self.storeResult()
 
 
@@ -226,7 +230,7 @@
             if 'call' in step:
                 return # XXX, fix this
             attrname = opcode2attrname(step)
-            body.append('self.builder.il.Emit(OpCodes.%s)' % attrname)
+            body.append('self.builder.parent.il.Emit(OpCodes.%s)' % attrname)
         elif isinstance(step, cli_opcodes.MapException):
             return # XXX, TODO
         else:

Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py	Wed May 14 12:31:27 2008
@@ -12,7 +12,6 @@
 OpCodes = System.Reflection.Emit.OpCodes
 
 DUMP_IL = False
-DEBUG = False
 
 cVoid = ootype.nullruntimeclass
 cInt32 = classof(System.Int32)
@@ -57,18 +56,18 @@
 
     def load(self, builder):
         if self.index == 0:
-            builder.il.Emit(OpCodes.Ldarg_0)
+            builder.parent.il.Emit(OpCodes.Ldarg_0)
         elif self.index == 1:
-            builder.il.Emit(OpCodes.Ldarg_1)
+            builder.parent.il.Emit(OpCodes.Ldarg_1)
         elif self.index == 2:
-            builder.il.Emit(OpCodes.Ldarg_2)
+            builder.parent.il.Emit(OpCodes.Ldarg_2)
         elif self.index == 3:
-            builder.il.Emit(OpCodes.Ldarg_3)
+            builder.parent.il.Emit(OpCodes.Ldarg_3)
         else:
-            builder.il.Emit(OpCodes.Ldarg, self.index)
+            builder.parent.il.Emit(OpCodes.Ldarg, self.index)
 
     def store(self, builder):
-        builder.il.Emit(OpCodes.Starg, self.index)
+        builder.parent.il.Emit(OpCodes.Starg, self.index)
 
     def __repr__(self):
         return "GenArgVar(%d)" % self.index
@@ -81,10 +80,10 @@
         return self.v.get_LocalType()
 
     def load(self, builder):
-        builder.il.Emit(OpCodes.Ldloc, self.v)
+        builder.parent.il.Emit(OpCodes.Ldloc, self.v)
 
     def store(self, builder):
-        builder.il.Emit(OpCodes.Stloc, self.v)
+        builder.parent.il.Emit(OpCodes.Stloc, self.v)
 
 
 class IntConst(GenConst):
@@ -108,7 +107,7 @@
         return class2type(self.cliclass)
 
     def load(self, builder):
-        builder.il.Emit(OpCodes.Ldc_I4, self.value)
+        builder.parent.il.Emit(OpCodes.Ldc_I4, self.value)
 
     def __repr__(self):
         return "int const=%s" % self.value
@@ -128,7 +127,7 @@
         return typeof(System.Double)
 
     def load(self, builder):
-        builder.il.Emit(OpCodes.Ldc_R8, self.value)
+        builder.parent.il.Emit(OpCodes.Ldc_R8, self.value)
 
     def __repr__(self):
         return "float const=%s" % self.value
@@ -145,10 +144,10 @@
         return index
 
     def _load_from_array(self, builder, index, clitype):
-        builder.il.Emit(OpCodes.Ldarg_0)
-        builder.il.Emit(OpCodes.Ldc_I4, index)
-        builder.il.Emit(OpCodes.Ldelem_Ref)
-        builder.il.Emit(OpCodes.Castclass, clitype)
+        builder.parent.il.Emit(OpCodes.Ldarg_0)
+        builder.parent.il.Emit(OpCodes.Ldc_I4, index)
+        builder.parent.il.Emit(OpCodes.Ldelem_Ref)
+        builder.parent.il.Emit(OpCodes.Castclass, clitype)
 
     def getobj(self):
         raise NotImplementedError
@@ -162,6 +161,7 @@
         return self.obj
 
     def load(self, builder):
+        import pdb;pdb.set_trace()
         index = self._get_index(builder)
         if self.obj is None:
             t = typeof(System.Object)
@@ -171,6 +171,10 @@
 
     @specialize.arg(1)
     def revealconst(self, T):
+        if T is ootype.Signed:
+            return 12345
+        elif T is ootype.Unsigned:
+            return 12346
         return ootype.cast_from_object(T, self.obj)
 
 
@@ -192,8 +196,8 @@
         delegatetype = self.delegatetype
         index = self._get_index(builder)
         self._load_from_array(builder, index, holdertype)
-        builder.il.Emit(OpCodes.Ldfld, funcfield)
-        builder.il.Emit(OpCodes.Castclass, delegatetype)
+        builder.parent.il.Emit(OpCodes.Ldfld, funcfield)
+        builder.parent.il.Emit(OpCodes.Castclass, delegatetype)
 
     @specialize.arg(1)
     def revealconst(self, T):
@@ -282,11 +286,11 @@
         for i in range(len(argsclass)):
             args[i+1] = class2type(argsclass[i])
         res = class2type(sigtoken.res)
-        builder = Builder(self, name, res, args, sigtoken)
+        builder = GraphBuilder(self, name, res, args, sigtoken)
         return builder, builder.gv_entrypoint, builder.inputargs_gv[:]
 
 
-class Builder(GenBuilder):
+class GraphBuilder(GenBuilder):
 
     def __init__(self, rgenop, name, res, args, sigtoken):
         self.rgenop = rgenop
@@ -300,123 +304,148 @@
             self.inputargs_gv.append(GenArgVar(i, args[i]))
         self.delegatetype = class2type(sigtoken.funcclass)
         self.gv_entrypoint = FunctionConst(self.delegatetype)
-        self.isOpen = False
-        self.operations = []
-        self.branches = []
-        self.returnblocks = []
         self.genconsts = {}
+        self.branches = [BranchBuilder(self, self.il.DefineLabel())]
+        restype = class2type(sigtoken.res)
+        if restype is not None:
+            self.retvar = self.il.DeclareLocal(restype)
+        else:
+            self.retvar = None
+        self.retlabel = self.il.DefineLabel()
+
+    def appendbranch(self, branchbuilder):
+        self.branches.append(branchbuilder)
+
+    def start_writing(self):
+        self.branches[0].start_writing()
+
+    def pause_writing(self, args_gv):
+        return self.branches[0].pause_writing(args_gv)
+ 
+    def finish_and_return(self, sigtoken, gv_returnvar):
+        return self.branches[0].finish_and_return(sigtoken,
+                                                  gv_returnvar)
+
+    def finish_and_goto(self, outputargs_gv, target):
+        return self.branches[0].finish_and_goto(outputargs_gv, target)
+
+    def enter_next_block(self, args_gv):
+        return self.branches[0].enter_next_block(args_gv)
+
+    def jump_if_false(self, gv_condition, args_for_jump_gv):
+        return self.branches[0].jump_if_false(gv_condition,
+                                              args_for_jump_gv)
+
+    def jump_if_true(self, gv_condition, args_for_jump_gv):
+        return self.branches[0].jump_if_true(gv_condition,
+                                             args_for_jump_gv)
 
     @specialize.arg(1)
     def genop1(self, opname, gv_arg):
-        opcls = ops.getopclass1(opname)
-        op = opcls(self, gv_arg)
-        self.emit(op)
-        gv_res = op.gv_res()
-        if DEBUG:
-            self.il.EmitWriteLine(opname)
-            self.writeline_gv(gv_arg)
-            self.writeline_gv(gv_res)
-            self.il.EmitWriteLine('')
-        return gv_res
+        return self.branches[0].genop1(opname, gv_arg)
     
     @specialize.arg(1)
     def genop2(self, opname, gv_arg1, gv_arg2):
-        opcls = ops.getopclass2(opname)
-        op = opcls(self, gv_arg1, gv_arg2)
-        self.emit(op)
-        gv_res = op.gv_res()
-        if DEBUG:
-            self.il.EmitWriteLine(opname)
-            self.writeline_gv(gv_arg1)
-            self.writeline_gv(gv_arg2)
-            self.writeline_gv(gv_res)
-            self.il.EmitWriteLine('')
-        return gv_res
-
-    def writeline_gv(self, gv):
-        if isinstance(gv, GenLocalVar):
-            self.il.EmitWriteLine(gv.v)
-        elif isinstance(gv, IntConst):
-            self.il.EmitWriteLine('%s' % gv.value)
-        else:
-            assert False
+        return self.branches[0].genop2(opname, gv_arg1, gv_arg2)
 
     def genop_call(self, sigtoken, gv_fnptr, args_gv):
-        op = ops.Call(self, sigtoken, gv_fnptr, args_gv)
-        self.emit(op)
-        return op.gv_res()
+        return self.branches[0].genop_call(sigtoken, gv_fnptr, args_gv)
 
     def genop_same_as(self, gv_x):
-        op = ops.SameAs(self, gv_x)
-        self.emit(op)
-        return op.gv_res()
+        return self.branches[0].genop_same_as(gv_x)
 
-    def genop_getfield(self, fieldtoken, gv_ptr):
-        pass
+    def end(self):
+        # render all the pending branches
+        for branchbuilder in self.branches:
+            branchbuilder.replayops()
 
-    def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
-        pass
+        # render the return block for last, else the verifier could complain        
+        self.il.MarkLabel(self.retlabel)
+        if self.retvar:
+            self.il.Emit(OpCodes.Ldloc, self.retvar)
+        self.il.Emit(OpCodes.Ret)
+
+        # initialize the array of genconsts
+        consts = new_array(System.Object, len(self.genconsts))
+        for gv_const, i in self.genconsts.iteritems():
+            consts[i] = gv_const.getobj()
+        # build the delegate
+        myfunc = self.meth.CreateDelegate(self.delegatetype, consts)
+        self.gv_entrypoint.holder.SetFunc(myfunc)
 
-    def emit(self, op):
-        op.emit()
 
-    def appendbranch(self, branch):
-        self.branches.append(branch)
+class BranchBuilder(GenBuilder):
 
-    def appendreturn(self, retlabel, gv_returnvar):
-        self.returnblocks.append((retlabel, gv_returnvar))
+    def __init__(self, parent, label):
+        self.parent = parent
+        self.label = label
+        self.operations = []
+        self.is_open = False
+        self.genconsts = parent.genconsts
 
     def start_writing(self):
-        self.isOpen = True
+        self.is_open = True
 
     def finish_and_return(self, sigtoken, gv_returnvar):
-        retlabel = self.il.DefineLabel()
-        op = ops.Branch(self, None, OpCodes.Br, retlabel)
-        self.emit(op)
-        self.appendreturn(retlabel, gv_returnvar)
-        self.isOpen = False
+        op = ops.Return(self, gv_returnvar)
+        self.appendop(op)
+        self.is_open = False
 
     def finish_and_goto(self, outputargs_gv, target):
         inputargs_gv = target.inputargs_gv
         assert len(inputargs_gv) == len(outputargs_gv)
-        op = ops.FollowLink(self, outputargs_gv, inputargs_gv, target.label)
-        self.emit(op)
-        self.isOpen = False
+        op = ops.FollowLink(self, outputargs_gv, inputargs_gv,
+                            target.label)
+        self.appendop(op)
+        self.is_open = False
 
-    def end(self):
-        # render all the pending branches
-        for branch in self.branches:
-            branch.replayops()
+    @specialize.arg(1)
+    def genop1(self, opname, gv_arg):
+        opcls = ops.getopclass1(opname)
+        op = opcls(self, gv_arg)
+        self.appendop(op)
+        gv_res = op.gv_res()
+        return gv_res
+    
+    @specialize.arg(1)
+    def genop2(self, opname, gv_arg1, gv_arg2):
+        opcls = ops.getopclass2(opname)
+        op = opcls(self, gv_arg1, gv_arg2)
+        self.appendop(op)
+        gv_res = op.gv_res()
+        return gv_res
 
-        # render the return blocks for last, else the verifier could complain
-        for retlabel, gv_returnvar in self.returnblocks:
-            self.il.MarkLabel(retlabel)
-            op = ops.Return(self, gv_returnvar)
-            self.emit(op)
+    def genop_call(self, sigtoken, gv_fnptr, args_gv):
+        op = ops.Call(self, sigtoken, gv_fnptr, args_gv)
+        self.appendop(op)
+        return op.gv_res()
 
-        # initialize the array of genconsts
-        consts = new_array(System.Object, len(self.genconsts))
-        for gv_const, i in self.genconsts.iteritems():
-            consts[i] = gv_const.getobj()
-        # build the delegate
-        myfunc = self.meth.CreateDelegate(self.delegatetype, consts)
-        self.gv_entrypoint.holder.SetFunc(myfunc)
+    def genop_same_as(self, gv_x):
+        op = ops.SameAs(self, gv_x)
+        self.appendop(op)
+        return op.gv_res()
+
+##    def genop_getfield(self, fieldtoken, gv_ptr):
+##        pass
+
+##    def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
+##        pass
 
     def enter_next_block(self, args_gv):
         for i in range(len(args_gv)):
             op = ops.SameAs(self, args_gv[i])
-            op.emit()
+            self.appendop(op)
             args_gv[i] = op.gv_res()
-        label = self.il.DefineLabel()
-        self.emit(ops.MarkLabel(self, label))
+        label = self.parent.il.DefineLabel()
+        self.appendop(ops.MarkLabel(self, label))
         return Label(label, args_gv)
 
     def _jump_if(self, gv_condition, opcode):
-        label = self.il.DefineLabel()
+        label = self.parent.il.DefineLabel()
         op = ops.Branch(self, gv_condition, opcode, label)
-        self.emit(op)
-        branch = BranchBuilder(self, label)
-        self.appendbranch(branch)
+        self.appendop(op)
+        branch = BranchBuilder(self.parent, label)
+        self.parent.appendbranch(branch)
         return branch
 
     def jump_if_false(self, gv_condition, args_for_jump_gv):
@@ -425,43 +454,16 @@
     def jump_if_true(self, gv_condition, args_for_jump_gv):
         return self._jump_if(gv_condition, OpCodes.Brtrue)
 
-class BranchBuilder(Builder):
-
-    def __init__(self, parent, label):
-        self.parent = parent
-        self.label = label
-        self.il = parent.il
-        self.operations = []
-        self.isOpen = False
-        self.genconsts = parent.genconsts
-
-    def start_writing(self):
-        self.isOpen = True
-
-    @specialize.arg(1)
-    def genop2(self, opname, gv_arg1, gv_arg2):
-        # XXX: this only serves to mask a bug in gencli which I don't
-        # feel like fixing now. Try to uncomment this and run
-        # test_goto_compile to see why it fails
-        return Builder.genop2(self, opname, gv_arg1, gv_arg2)
-
-    def emit(self, op):
+    def appendop(self, op):
         self.operations.append(op)
 
-    def appendbranch(self, branch):
-        self.parent.appendbranch(branch)
-
-    def appendreturn(self, retlabel, gv_returnvar):
-        self.parent.appendreturn(retlabel, gv_returnvar)
-
     def end(self):
         self.parent.end()
 
     def replayops(self):
-        assert not self.isOpen
-        assert not self.parent.isOpen
+        assert not self.is_open
         il = self.parent.il
-        il.MarkLabel(self.label)        
+        il.MarkLabel(self.label)
         for op in self.operations:
             op.emit()
 

Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py	Wed May 14 12:31:27 2008
@@ -1,9 +1,11 @@
 import py
 from pypy.jit.codegen.cli.rgenop import RCliGenOp
+from pypy.jit.codegen.dump.rgenop import RDumpGenOp
 from pypy.jit.rainbow.test.test_interpreter import TestOOType as RainbowTest
 
 class TestRainbowCli(RainbowTest):
     RGenOp = RCliGenOp
+    RGenOp = RDumpGenOp
 
     # for the individual tests see
     # ====> ../../../rainbow/test/test_interpreter.py
@@ -23,7 +25,7 @@
 
     test_simple_opt_const_propagation1 = skip
     test_simple_opt_const_propagation2 = skip
-    test_red_switch = skip
+    #test_red_switch = skip
     test_merge = skip
     test_loop_merging = skip
     test_loop_merging2 = skip

Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py	Wed May 14 12:31:27 2008
@@ -70,11 +70,8 @@
         py.test.skip('fixme: add support for frames')
 
     def test_from_random_direct(self):
-        py.test.skip('mono crashes')
-        
-    def test_from_random_3_direct(self):
-        py.test.skip('infinite loop')
-        
+        py.test.skip('mono crash')
+
     def test_from_random_5_direct(self):
         py.test.skip('mono crash')
 

Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py	Wed May 14 12:31:27 2008
@@ -2670,3 +2670,34 @@
 
         fnptr = self.cast(gv_fn, 0, RESULT=lltype.Void)
         #res = fnptr() -- xxx fix me, cannot be run so far
+
+    def test_red_switch(self):
+        """
+        This code is derived from the one produced by the dump backend
+        when running rainbow.test_interpreter.test_red_switch.
+        """
+        rgenop = self.RGenOp()
+        sigtoken = rgenop.sigToken(self.T.FUNC2)
+
+        builder0, gv_callable, [arg1, arg2] = rgenop.newgraph(sigtoken,
+                                                          'generated')
+        builder0.start_writing()
+        var0 = builder0.genop1('int_is_true', arg1)
+        builder1 = builder0.jump_if_false(var0, [arg1, arg2, var0])
+        builder1.start_writing()
+        args_gv = [arg2]
+        label0 = builder1.enter_next_block(args_gv)
+        [v3] = args_gv
+        builder0.start_writing()
+        builder0.finish_and_goto([arg1], label0)
+        builder1.start_writing()
+        args_gv = [v3]
+        label1 = builder1.enter_next_block(args_gv)
+        [v4] = args_gv
+        builder1.finish_and_return(sigtoken, v4)
+        builder0.end()
+
+        fnptr = self.cast(gv_callable, 2)
+        result = fnptr(1, 2)
+        assert result == 1
+



More information about the Pypy-commit mailing list