[pypy-svn] r65314 - in pypy/branch/pyjitpl5/pypy: jit/backend/cli jit/backend/cli/test translator/cli/src

antocuni at codespeak.net antocuni at codespeak.net
Tue May 19 17:28:41 CEST 2009


Author: antocuni
Date: Tue May 19 17:28:40 2009
New Revision: 65314

Modified:
   pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py
   pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py
   pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py
   pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs
Log:
implement bridges; so far the implementation is very simple, just a tailcall
to the method containing the next loop; hopefully, the speed penalty
associated to the tail call is not too heavy, because we don't expect bridges
to be so frequent (thanks cfbolz for the idea).  In the future, we might think
of other techniques to avoid tail calls.



Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/method.py	Tue May 19 17:28:40 2009
@@ -14,6 +14,7 @@
 System = CLR.System
 OpCodes = System.Reflection.Emit.OpCodes
 LoopDelegate = CLR.pypy.runtime.LoopDelegate
+DelegateHolder = CLR.pypy.runtime.DelegateHolder
 InputArgs = CLR.pypy.runtime.InputArgs
 
 cVoid = ootype.nullruntimeclass
@@ -51,12 +52,40 @@
     def store(self, meth):
         assert False, 'cannot store() to Constant'
 
+    def get_cliobj(self):
+        return dotnet.cast_to_native_object(self.getobj())
+
 class __extend__(ConstInt):
     __metaclass__ = extendabletype
 
     def load(self, meth):
         meth.il.Emit(OpCodes.Ldc_I4, self.value)
 
+
+class ConstFunction(Const):
+
+    def __init__(self, name):
+        self.name = name
+        self.holder = DelegateHolder()
+
+    def get_cliobj(self):
+        return dotnet.cliupcast(self.holder, System.Object)
+
+    def load(self, meth):
+        holdertype = self.holder.GetType()
+        funcfield = holdertype.GetField('func')
+        Const.load(self, meth)
+        meth.il.Emit(OpCodes.Castclass, holdertype)
+        meth.il.Emit(OpCodes.Ldfld, funcfield)
+        meth.il.Emit(OpCodes.Castclass, dotnet.typeof(LoopDelegate))
+
+    def _getrepr_(self):
+        return '<ConstFunction %s>' % self.name
+
+    def __hash__(self):
+        return hash(self.holder)
+
+
 class MethodArgument(AbstractValue):
     def __init__(self, index, cliType):
         self.index = index
@@ -87,6 +116,7 @@
 class Method(object):
 
     operations = [] # overwritten at the end of the module
+    tailcall = True
     debug = False
 
     def __init__(self, cpu, name, loop):
@@ -124,10 +154,12 @@
         # initialize the array of genconsts
         consts = dotnet.new_array(System.Object, len(self.consts))
         for av_const, i in self.consts.iteritems():
-            consts[i] = dotnet.cast_to_native_object(av_const.getobj())
+            #consts[i] = dotnet.cast_to_native_object(av_const.getobj())
+            consts[i] = av_const.get_cliobj()
         # build the delegate
         func = self.meth_wrapper.create_delegate(delegatetype, consts)
-        self.func = dotnet.clidowncast(func, LoopDelegate)
+        func = dotnet.clidowncast(func, LoopDelegate)
+        self.loop._cli_funcbox.holder.SetFunc(func)
 
     def _get_meth_wrapper(self):
         restype = dotnet.class2type(cVoid)
@@ -282,7 +314,10 @@
         self.il.Emit(OpCodes.Ldc_I4, index_op)
         field = dotnet.typeof(InputArgs).GetField('failed_op')
         self.il.Emit(OpCodes.Stfld, field)
-        # store the lates values
+        self.emit_store_opargs(op)
+
+    def emit_store_opargs(self, op):
+        # store the latest values
         i = 0
         for box in op.args:
             self.store_inputarg(i, box.type, box.getCliType(), box)
@@ -344,13 +379,23 @@
 
     def emit_op_jump(self, op):
         target = op.jump_target
-        assert target is self.loop, 'TODO'
         assert len(op.args) == len(target.inputargs)
-        i = 0
-        for i in range(len(op.args)):
-            op.args[i].load(self)
-            target.inputargs[i].store(self)
-        self.il.Emit(OpCodes.Br, self.il_loop_start)
+        if target is self.loop:
+            i = 0
+            for i in range(len(op.args)):
+                op.args[i].load(self)
+                target.inputargs[i].store(self)
+            self.il.Emit(OpCodes.Br, self.il_loop_start)
+        else:
+            # it's a real bridge
+            self.emit_store_opargs(op)
+            self.av_inputargs.load(self)
+            self.loop._cli_funcbox.load(self)
+            methinfo = dotnet.typeof(LoopDelegate).GetMethod('Invoke')
+            if self.tailcall:
+                self.il.Emit(OpCodes.Tailcall)
+            self.il.Emit(OpCodes.Callvirt, methinfo)
+            self.il.Emit(OpCodes.Ret)
 
     def emit_op_new_with_vtable(self, op):
         assert isinstance(op.args[0], ConstObj) # ignored, using the descr instead

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/runner.py	Tue May 19 17:28:40 2009
@@ -1,6 +1,9 @@
+from pypy.tool.pairtype import extendabletype
 from pypy.rpython.ootypesystem import ootype
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.history import AbstractDescr, AbstractMethDescr
-from pypy.jit.metainterp.history import Box, BoxInt, BoxObj
+from pypy.jit.metainterp.history import Box, BoxInt, BoxObj, ConstObj, Const
+from pypy.jit.metainterp.history import TreeLoop
 from pypy.jit.metainterp import executor
 from pypy.jit.metainterp.resoperation import rop, opname
 from pypy.jit.backend import model
@@ -12,6 +15,12 @@
 System = CLR.System
 InputArgs = CLR.pypy.runtime.InputArgs
 
+class __extend__(TreeLoop):
+    __metaclass__ = extendabletype
+
+    _cli_funcbox = None
+    _cli_meth = None
+
 
 class CliCPU(model.AbstractCPU):
 
@@ -67,13 +76,18 @@
     # ----------------------
 
     def compile_operations(self, loop):
-        from pypy.jit.backend.cli.method import Method
-        meth = Method(self, loop.name, loop)
-        loop._cli_meth = meth
+        from pypy.jit.backend.cli.method import Method, ConstFunction
+        if loop._cli_funcbox is None:
+            loop._cli_funcbox = ConstFunction(loop.name)
+        else:
+            # discard previously compiled loop
+            loop._cli_funcbox.holder.SetFunc(None)
+        loop._cli_meth = Method(self, loop.name, loop)
 
     def execute_operations(self, loop):
         meth = loop._cli_meth
-        meth.func(self.get_inputargs())
+        func = loop._cli_funcbox.holder.GetFunc()
+        func(self.get_inputargs())
         return meth.failing_ops[self.inputargs.get_failed_op()]
 
     def set_future_value_int(self, index, intvalue):

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/cli/test/test_basic.py	Tue May 19 17:28:40 2009
@@ -37,7 +37,7 @@
     test_oostring_instance = skip
     test_long_long = skip
     test_free_object = skip
+    test_stopatxpolicy = skip
     
-    test_stopatxpolicy = _skip
     test_bridge_from_interpreter = _skip
-    test_bridge_from_interpreter_4 = _skip
+

Modified: pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs
==============================================================================
--- pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs	(original)
+++ pypy/branch/pyjitpl5/pypy/translator/cli/src/pypylib.cs	Tue May 19 17:28:40 2009
@@ -291,24 +291,25 @@
             return default_blockid;
         }
     }
+  */
         
     public class DelegateHolder
     {
-        public Delegate func;
+        public LoopDelegate func;
 
         // we need getter and setter because we can't directly access fields from RPython
-        public void SetFunc(Delegate func)
+        public void SetFunc(LoopDelegate func)
         {
             this.func = func;
         }
 
-        public Delegate GetFunc()
+        public LoopDelegate GetFunc()
         {
             return this.func;
         }
     }
 
-  */
+
 
     public class AutoSaveAssembly
     {



More information about the Pypy-commit mailing list