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

antocuni at codespeak.net antocuni at codespeak.net
Thu Jul 24 11:16:24 CEST 2008


Author: antocuni
Date: Thu Jul 24 11:16:23 2008
New Revision: 56763

Modified:
   pypy/branch/oo-jit/pypy/jit/codegen/cli/methodfactory.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_rgenop.py
Log:
yahi! The first flexswitch test passes :-)



Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/methodfactory.py
==============================================================================
--- pypy/branch/oo-jit/pypy/jit/codegen/cli/methodfactory.py	(original)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/methodfactory.py	Thu Jul 24 11:16:23 2008
@@ -32,6 +32,7 @@
 class AssemblyData:
     assembly = None
     name = None
+    methcount = 0
 
     def is_enabled(self):
         if self.name is None:
@@ -56,6 +57,8 @@
     
     def __init__(self, name, res, args):
         module = assemblyData.module
+        name = '%s_%d' % (name, assemblyData.methcount)
+        assemblyData.methcount += 1
         self.typeBuilder = AutoSaveAssembly.DefineType(module, name)
         self.meth = AutoSaveAssembly.DefineMethod(self.typeBuilder,
                                                   "invoke", res, args)

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	Thu Jul 24 11:16:23 2008
@@ -13,12 +13,10 @@
         return self.gv_x.getCliType()
 
     def gv_res(self):
-        from pypy.jit.codegen.cli.rgenop import GenLocalVar
         if self._gv_res is None:
             restype = self.restype()
             if restype is not None:
-                loc = self.meth.il.DeclareLocal(restype)
-                self._gv_res = GenLocalVar(loc)
+                self._gv_res = self.meth.newlocalvar(restype)
         return self._gv_res
 
     def emit(self):
@@ -127,12 +125,29 @@
         return None
 
     def emit(self):
-        retvar = self.meth.retvar
-        il_retlabel = self.meth.il_retlabel
+        gv_retvar = self.meth.gv_retvar
+        retlabel = self.meth.retlabel
         if self.gv_x is not None:
             self.gv_x.load(self.meth)
-            self.meth.il.Emit(OpCodes.Stloc, retvar)
-        self.meth.il.Emit(OpCodes.Br, il_retlabel)
+            gv_retvar.store(self.meth)
+        self.meth.il.Emit(OpCodes.Br, retlabel.il_label)
+
+class ReturnFromFlexSwitch(Operation):
+
+    def __init__(self, meth, gv_x):
+        self.meth = meth
+        self.gv_x = gv_x
+
+    def restype(self):
+        return None
+
+    def emit(self):
+        il = self.meth.il
+        manager = InputArgsManager(self.meth, [self.gv_x])
+        manager.copy_from_args()
+        blockid = self.meth.graphinfo.graph_retlabel.blockid
+        il.Emit(OpCodes.Ldc_I4, blockid)
+        il.Emit(OpCodes.Ret)
 
 class Call(Operation):
 
@@ -193,6 +208,10 @@
         self.gv_value.load(self.meth)
         self.meth.il.Emit(OpCodes.Stfld, self.fieldinfo)
 
+def mark(il, s):
+    il.Emit(OpCodes.Ldstr, s)
+    il.Emit(OpCodes.Pop)
+
 class DoFlexSwitch(Operation):
 
     def __init__(self, meth, gv_flexswitch, gv_exitswitch, args_gv):
@@ -205,40 +224,39 @@
         return None
 
     def emit(self):
-        mbuilder = self.meth
-        il = mbuilder.il
+        graph = self.meth
+        il = graph.il
         # get MethodInfo for LowLevelFlexSwitch.execute
         clitype = self.gv_flexswitch.flexswitch.GetType()
         meth_execute = clitype.GetMethod('execute')
 
         # setup the correct inputargs
-        manager = InputArgsManager(mbuilder, self.args_gv)
-        manager.copy_from_args(mbuilder)
+        manager = InputArgsManager(graph, self.args_gv)
+        manager.copy_from_args()
 
         # jumpto = flexswitch.execute(exitswitch, inputargs);
         # goto dispatch_jump;
-        self.gv_flexswitch.load(mbuilder)
-        self.gv_exitswitch.load(mbuilder)
-        il.Emit(OpCodes.Ldloc, mbuilder.inputargs_var)
+        self.gv_flexswitch.load(graph)
+        self.gv_exitswitch.load(graph)
+        graph.gv_inputargs.load(graph)
         il.Emit(OpCodes.Callvirt, meth_execute)
-        il.Emit(OpCodes.Stloc, mbuilder.jumpto_var)
-        il.Emit(OpCodes.Br, mbuilder.il_dispatch_jump_label)
+        il.Emit(OpCodes.Stloc, graph.jumpto_var)
+        il.Emit(OpCodes.Br, graph.il_dispatch_jump_label)
 
 
 class InputArgsManager:
 
     def __init__(self, meth, args_gv):
-        self.inputargs_var = meth.inputargs_var
-        self.inputargs_clitype = meth.inputargs_clitype
+        self.meth = meth
         self.args_gv = args_gv
 
     def basename_from_type(self, clitype):
         return clitype.get_Name()
 
-    def copy_from_args(self, meth):
-        il = meth.meth.il
-        inputargs_var = self.inputargs_var
-        inputargs_clitype = self.inputargs_clitype
+    def _get_fields(self):
+        fields = []
+        gv_inputargs = self.meth.gv_inputargs
+        inputargs_clitype = gv_inputargs.getCliType()
         counters = {}
         for gv_arg in self.args_gv:
             clitype = gv_arg.getCliType()
@@ -247,11 +265,33 @@
             fieldname = '%s_%d' % (basename, count)
             counters[clitype] = count+1
             field = inputargs_clitype.GetField(fieldname)
+            fields.append(field)
+        return fields
 
-            il.Emit(OpCodes.Ldloc, inputargs_var)
-            gv_arg.load(builder)
+    def copy_from_args(self):
+        il = self.meth.il
+        gv_inputargs = self.meth.gv_inputargs
+        fields = self._get_fields()
+        assert len(self.args_gv) == len(fields)
+        for i in range(len(self.args_gv)):
+            gv_arg = self.args_gv[i]
+            field = fields[i]
+            gv_inputargs.load(self.meth)
+            gv_arg.load(self.meth)
             il.Emit(OpCodes.Stfld, field)
 
+    def copy_to_args(self):
+        il = self.meth.il
+        gv_inputargs = self.meth.gv_inputargs
+        fields = self._get_fields()
+        assert len(self.args_gv) == len(fields)
+        for i in range(len(self.args_gv)):
+            gv_arg = self.args_gv[i]
+            field = fields[i]
+            gv_inputargs.load(self.meth)
+            il.Emit(OpCodes.Ldfld, field)
+            gv_arg.store(self.meth)
+
 class WriteLine(Operation):
 
     def __init__(self, meth, message):

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	Thu Jul 24 11:16:23 2008
@@ -26,6 +26,7 @@
 cChar = classof(System.Char)
 cInputArgs = classof(InputArgs)
 cUtils = classof(CLR.pypy.runtime.Utils)
+cFlexSwitchCase = classof(CLR.pypy.runtime.FlexSwitchCase)
 
 class SigToken:
     def __init__(self, args, res, funcclass):
@@ -233,11 +234,20 @@
 
 
 class Label(GenLabel):
-    def __init__(self, blockid, il_label, inputargs_gv):
+    def __init__(self, blockid, il, inputargs_gv):
         self.blockid = blockid
-        self.il_label = il_label
+        self.il_label = il.DefineLabel()
+        self.il_trampoline_label = il.DefineLabel()
         self.inputargs_gv = inputargs_gv
 
+    def emit_trampoline(self, meth):
+        from pypy.jit.codegen.cli.operation import InputArgsManager
+        from pypy.jit.codegen.cli.operation import mark
+        il = meth.il
+        manager = InputArgsManager(meth, self.inputargs_gv)
+        il.MarkLabel(self.il_trampoline_label)
+        manager.copy_to_args()
+        il.Emit(OpCodes.Br, self.il_label)
 
 class RCliGenOp(AbstractRGenOp):
 
@@ -328,14 +338,11 @@
         pass
 
     def newgraph(self, sigtoken, name):
-        argsclass = sigtoken.args
-        args = new_array(System.Type, len(argsclass)+1)
-        args[0] = System.Type.GetType("System.Object[]")
-        for i in range(len(argsclass)):
-            args[i+1] = class2type(argsclass[i])
+        arglist = [class2type(cls) for cls in sigtoken.args]
         restype = class2type(sigtoken.res)
         delegatetype = class2type(sigtoken.funcclass)
-        graph = GraphGenerator(self, name, restype, args, delegatetype)
+        graph = GraphGenerator(self, name, restype, arglist,
+                               delegatetype)
         builder = graph.branches[0]
         return builder, graph.gv_entrypoint, graph.inputargs_gv[:]
 
@@ -344,11 +351,16 @@
     def __init__(self):
         self.has_flexswitches = False
         self.blocks = [] # blockid -> (meth, label)
+        self.flexswitch_meths = []
+        self.main_retlabel = None
 
 class MethodGenerator:
     
-    def __init__(self, rgenop, name, restype, args, delegatetype, graphinfo):
+    def __init__(self, rgenop, name, restype, arglist,
+                 delegatetype, graphinfo):
         self.rgenop = rgenop
+        self.name = name
+        args = self._get_args_array(arglist)
         self.meth_wrapper = get_method_wrapper(name, restype, args)
         self.il = self.meth_wrapper.get_il_generator()
         self.inputargs_gv = []
@@ -356,16 +368,25 @@
         for i in range(1, len(args)):
             self.inputargs_gv.append(GenArgVar(i, args[i]))
         self.delegatetype = delegatetype
+        self.graphinfo = graphinfo
+
         self.gv_entrypoint = FunctionConst(delegatetype)
         self.genconsts = {}
         self.branches = []
         self.newbranch()
-        if restype is not None:
-            self.retvar = self.il.DeclareLocal(restype)
+        if restype is None:
+            self.gv_retvar = None
+            self.retlabel = self.newblock([])
         else:
-            self.retvar = None
-        self.il_retlabel = self.il.DefineLabel()
-        self.graphinfo = graphinfo
+            self.gv_retvar = self.newlocalvar(restype)
+            self.retlabel = self.newblock([self.gv_retvar])
+
+    def _get_args_array(self, arglist):
+        array = new_array(System.Type, len(arglist)+1)
+        array[0] = System.Type.GetType("System.Object[]")
+        for i in range(len(arglist)):
+            array[i+1] = arglist[i]
+        return array
 
     def newbranch(self):
         branch = BranchBuilder(self, self.il.DefineLabel())
@@ -375,10 +396,19 @@
     def newblock(self, args_gv):
         blocks = self.graphinfo.blocks
         blockid = len(blocks)
-        result = Label(blockid, self.il.DefineLabel(), args_gv)
+        result = Label(blockid, self.il, args_gv)
         blocks.append((self, result))
         return result
 
+    def newlocalvar(self, clitype):
+        return GenLocalVar(self.il.DeclareLocal(clitype))
+
+    def map_genvar(self, gv_var):
+        return gv_var
+
+    def get_op_Return(self, gv_returnvar):
+        raise NotImplementedError
+
     def emit_code(self):
         # emit initialization code
         self.emit_preamble()
@@ -390,10 +420,11 @@
         # emit dispatch_jump, if there are flexswitches
         self.emit_before_returnblock()
 
-        # render the return block for last, else the verifier could complain        
-        self.il.MarkLabel(self.il_retlabel)
-        if self.retvar:
-            self.il.Emit(OpCodes.Ldloc, self.retvar)
+        # emit the return block at last, else the verifier complains
+        self.il.MarkLabel(self.retlabel.il_label)
+        if self.gv_retvar:
+            self.gv_retvar.load(self)
+
         self.il.Emit(OpCodes.Ret)
 
         # initialize the array of genconsts
@@ -415,37 +446,50 @@
     def __init__(self, rgenop, name, restype, args, delegatetype):
         graphinfo = GraphInfo()
         MethodGenerator.__init__(self, rgenop, name, restype, args, delegatetype, graphinfo)
+        graphinfo.graph_retlabel = self.retlabel
 
     def setup_flexswitches(self):
         if self.graphinfo.has_flexswitches:
             return
         self.graphinfo.has_flexswitches = True
         self.il_dispatch_jump_label = self.il.DefineLabel()
-        self.inputargs_clitype = class2type(cInputArgs)
-        self.inputargs_var = self.il.DeclareLocal(self.inputargs_clitype)
+        self.gv_inputargs = self.newlocalvar(class2type(cInputArgs))
         self.jumpto_var = self.il.DeclareLocal(class2type(cInt32))
 
+    def get_op_Return(self, gv_returnvar):
+        return ops.Return(self, gv_returnvar)
+
+    def emit_code(self):
+        self.emit_flexswitches()
+        MethodGenerator.emit_code(self)
+
+    def emit_flexswitches(self):
+        for meth in self.graphinfo.flexswitch_meths:
+            meth.emit_code()
+
     def emit_preamble(self):
         if not self.graphinfo.has_flexswitches:
             return        
         # InputArgs inputargs_var = new InputArgs()
-        clitype = class2type(cInputArgs)
+        clitype = self.gv_inputargs.getCliType()
         ctor = clitype.GetConstructor(new_array(System.Type, 0))
         self.il.Emit(OpCodes.Newobj, ctor)
-        self.il.Emit(OpCodes.Stloc, self.inputargs_var)
+        self.gv_inputargs.store(self)
 
     def emit_before_returnblock(self):
         if not self.graphinfo.has_flexswitches:
             return
         # make sure we don't enter dispatch_jump by mistake
-        self.il.Emit(OpCodes.Br, self.il_retlabel)
+        self.il.Emit(OpCodes.Br, self.retlabel.il_label)
         self.il.MarkLabel(self.il_dispatch_jump_label)
 
-        il_labels = new_array(System.Reflection.Emit.Label,
-                           len(self.graphinfo.blocks))
-        for blockid, (builder, label) in self.graphinfo.blocks:
-            assert builder is self
-            il_labels[blockid] = label.il_label
+        blocks = self.graphinfo.blocks
+        il_labels = new_array(System.Reflection.Emit.Label, len(blocks))
+        for blockid in range(len(blocks)):
+            builder, label = blocks[blockid]
+            if builder is not self:
+                continue # XXX FIXME
+            il_labels[blockid] = label.il_trampoline_label
 
         self.il.Emit(OpCodes.Ldloc, self.jumpto_var)
         self.il.Emit(OpCodes.Switch, il_labels)
@@ -456,6 +500,51 @@
         self.il.Emit(OpCodes.Ldloc, self.jumpto_var)
         self.il.Emit(OpCodes.Call, meth)
 
+        # emit all the trampolines to the blocks
+        for builder, label in blocks:
+            if builder is not self:
+                continue #XXX?
+            label.emit_trampoline(self)
+
+class FlexSwitchCaseGenerator(MethodGenerator):
+    flexswitch = None
+    value = -1
+    linkargs_gv = None
+    linkargs_gv_map = None
+
+    def set_parent_flexswitch(self, flexswitch, value):
+        self.parent_flexswitch = flexswitch
+        self.value = value
+
+    def set_linkargs_gv(self, linkargs_gv):
+        self.linkargs_gv = linkargs_gv
+        self.linkargs_gv_map = {}
+        for gv_arg in linkargs_gv:
+            gv_local = self.newlocalvar(gv_arg.getCliType())
+            self.linkargs_gv_map[gv_arg] = gv_local
+
+        self.gv_inputargs = self.inputargs_gv[1] # InputArgs is always the 2nd argument
+
+    def map_genvar(self, gv_var):
+        return self.linkargs_gv_map.get(gv_var, gv_var)
+
+    def get_op_Return(self, gv_returnvar):
+        return ops.ReturnFromFlexSwitch(self, gv_returnvar)
+
+    def emit_code(self):
+        MethodGenerator.emit_code(self)
+        func = self.gv_entrypoint.holder.GetFunc()
+        self.parent_flexswitch.llflexswitch.add_case(self.value, func)
+
+    def emit_preamble(self):
+        from pypy.jit.codegen.cli.operation import InputArgsManager
+        linkargs_out_gv = []
+        for gv_linkarg in self.linkargs_gv:
+            gv_var = self.linkargs_gv_map[gv_linkarg]
+            linkargs_out_gv.append(gv_var)
+        manager = InputArgsManager(self, linkargs_out_gv)
+        manager.copy_to_args()
+
 
 class BranchBuilder(GenBuilder):
 
@@ -471,7 +560,7 @@
         self.is_open = True
 
     def finish_and_return(self, sigtoken, gv_returnvar):
-        op = ops.Return(self.meth, gv_returnvar)
+        op = self.meth.get_op_Return(gv_returnvar)
         self.appendop(op)
         self.is_open = False
 
@@ -493,6 +582,10 @@
     
     @specialize.arg(1)
     def genop2(self, opname, gv_arg1, gv_arg2):
+        # XXX: also other ops
+        gv_arg1 = self.meth.map_genvar(gv_arg1)
+        gv_arg2 = self.meth.map_genvar(gv_arg2)
+        
         opcls = ops.getopclass2(opname)
         op = opcls(self.meth, gv_arg1, gv_arg2)
         self.appendop(op)
@@ -547,11 +640,10 @@
     def flexswitch(self, gv_exitswitch, args_gv):
         # XXX: this code is valid only for GraphGenerator
         self.meth.setup_flexswitches()
-        flexswitch = IntFlexSwitch()
-        flexswitch.xxxbuilder = self.meth.newbranch()
+        flexswitch = IntFlexSwitch(self.meth, args_gv)
         gv_flexswitch = flexswitch.gv_flexswitch
         default_branch = self.meth.newbranch()
-        label = default_branch.label
+        label = default_branch.enter_next_block(args_gv)
         flexswitch.llflexswitch.set_default_blockid(label.blockid)
         op = ops.DoFlexSwitch(self.meth, gv_flexswitch,
                               gv_exitswitch, args_gv)
@@ -575,14 +667,26 @@
 
 class IntFlexSwitch(CodeGenSwitch):
 
-    def __init__(self):
+    def __init__(self, graph, linkargs_gv):
+        self.graph = graph
+        self.linkargs_gv = linkargs_gv
         self.llflexswitch = LowLevelFlexSwitch()
         self.gv_flexswitch = FlexSwitchConst(self.llflexswitch)
 
     def add_case(self, gv_case):
-        return self.xxxbuilder
-        #import pdb;pdb.set_trace()
-
+        graph = self.graph
+        name = graph.name + '_case'
+        restype = class2type(cInt32)
+        arglist = [class2type(cInt32), class2type(cInputArgs)]
+        delegatetype = class2type(cFlexSwitchCase)
+        graphinfo = graph.graphinfo
+        meth = FlexSwitchCaseGenerator(graph.rgenop, name, restype,
+                                       arglist, delegatetype, graphinfo)
+        graphinfo.flexswitch_meths.append(meth)
+        value = gv_case.revealconst(ootype.Signed)
+        meth.set_parent_flexswitch(self, value)
+        meth.set_linkargs_gv(self.linkargs_gv)
+        return meth.branches[0]
 
 
 global_rgenop = RCliGenOp()

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	Thu Jul 24 11:16:23 2008
@@ -33,9 +33,6 @@
     def test_float_loop_direct(self):
         py.test.skip('fixme')
 
-    def test_switch_direct(self):
-        py.test.skip('in-progress')
-
     def test_large_switch_direct(self):
         py.test.skip('no promotion/flexswitch for now please :-)')
 



More information about the Pypy-commit mailing list