[pypy-svn] r55327 - in pypy/branch/oo-jit/pypy: jit/codegen/cli jit/codegen/cli/test translator/cli/src

antocuni at codespeak.net antocuni at codespeak.net
Wed May 28 10:32:59 CEST 2008


Author: antocuni
Date: Wed May 28 10:32:56 2008
New Revision: 55327

Added:
   pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py   (contents, props changed)
Removed:
   pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py
Modified:
   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/translator/cli/src/pypylib.cs
Log:
add a way to dump the generated methods into an assembly if PYPYJITLOG
is set



Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py
==============================================================================
--- (empty file)
+++ pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py	Wed May 28 10:32:56 2008
@@ -0,0 +1,80 @@
+import os
+from pypy.translator.cli.dotnet import CLR
+from pypy.translator.cli import dotnet
+System = CLR.System
+Utils = CLR.pypy.runtime.Utils
+AutoSaveAssembly = CLR.pypy.runtime.AutoSaveAssembly
+MethodAttributes = System.Reflection.MethodAttributes
+TypeAttributes = System.Reflection.TypeAttributes
+
+class AbstractMethodBuilder:
+    
+    def get_il_generator(self):
+        raise NotImplementedError
+
+    def create_delegate(self, delegatetype, consts):
+        raise NotImplementedError
+
+class DynamicMethodBuilder(AbstractMethodBuilder):
+    
+    def __init__(self, name, res, args):
+        self.dynmeth = Utils.CreateDynamicMethod(name, res, args)
+
+    def get_il_generator(self): 
+        return self.dynmeth.GetILGenerator()
+
+    def create_delegate(self, delegatetype, consts):
+        return self.dynmeth.CreateDelegate(delegatetype, consts)
+
+
+# the assemblyData singleton contains the informations about the
+# assembly we are currently writing to
+class AssemblyData:
+    assembly = None
+    name = None
+
+    def is_enabled(self):
+        if self.name is None:
+            name = os.environ.get('PYPYJITLOG')
+            if name is None:
+                name = ''
+            self.name = name
+        return bool(self.name)
+
+    def create(self):
+        assert self.is_enabled()
+        if self.assembly is None:
+            name = self.name
+            self.auto_save_assembly = AutoSaveAssembly.Create(name)
+            self.assembly = self.auto_save_assembly.GetAssemblyBuilder()
+            self.module = self.assembly.DefineDynamicModule(name)
+        
+assemblyData = AssemblyData()
+
+
+class AssemblyMethodBuilder(AbstractMethodBuilder):
+    
+    def __init__(self, name, res, args):
+        module = assemblyData.module
+        self.typeBuilder = AutoSaveAssembly.DefineType(module, name)
+        self.meth = AutoSaveAssembly.DefineMethod(self.typeBuilder,
+                                                  "invoke", res, args)
+
+
+    def get_il_generator(self):
+        return self.meth.GetILGenerator()
+
+    def create_delegate(self, delegatetype, consts):
+        t = self.typeBuilder.CreateType()
+        methinfo = t.GetMethod("invoke")
+        return System.Delegate.CreateDelegate(delegatetype,
+                                              consts,
+                                              methinfo)
+
+def get_methodbuilder(name, res, args):
+    if assemblyData.is_enabled():
+        assemblyData.create()
+        return AssemblyMethodBuilder(name, res, args)
+    else:
+        return DynamicMethodBuilder(name, res, args)
+

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 28 10:32:56 2008
@@ -6,16 +6,13 @@
 from pypy.jit.codegen.model import AbstractRGenOp, GenBuilder, GenLabel
 from pypy.jit.codegen.model import GenVarOrConst, GenVar, GenConst, CodeGenSwitch
 from pypy.jit.codegen.cli import operation as ops
-from pypy.jit.codegen.cli.dumpgenerator import DumpGenerator
+from pypy.jit.codegen.cli.methodbuilder import get_methodbuilder
 from pypy.translator.cli.dotnet import CLR, typeof, new_array, box, unbox, clidowncast, classof
 from pypy.translator.cli import dotnet
 System = CLR.System
-Utils = CLR.pypy.runtime.Utils
 DelegateHolder = CLR.pypy.runtime.DelegateHolder
 OpCodes = System.Reflection.Emit.OpCodes
 
-DUMP_IL = False
-
 cVoid = ootype.nullruntimeclass
 cInt32 = classof(System.Int32)
 cBoolean = classof(System.Boolean)
@@ -325,10 +322,8 @@
 
     def __init__(self, rgenop, name, res, args, sigtoken):
         self.rgenop = rgenop
-        self.meth = Utils.CreateDynamicMethod(name, res, args)
-        self.il = self.meth.GetILGenerator()
-        if DUMP_IL:
-            self.il = DumpGenerator(self.il)
+        self.meth = get_methodbuilder(name, res, args)
+        self.il = self.meth.get_il_generator()
         self.inputargs_gv = []
         # we start from 1 because the 1st arg is an Object[] containing the genconsts
         for i in range(1, len(args)):
@@ -416,7 +411,7 @@
         for gv_const, i in self.genconsts.iteritems():
             consts[i] = gv_const.getobj()
         # build the delegate
-        myfunc = self.meth.CreateDelegate(self.delegatetype, consts)
+        myfunc = self.meth.create_delegate(self.delegatetype, consts)
         self.gv_entrypoint.holder.SetFunc(myfunc)
 
 

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 28 10:32:56 2008
@@ -7,7 +7,6 @@
     RGenOp = RCliGenOp
 
     def _invoke(self, generated, residualargs):
-        
         # mono sucks; if we call the generated function directly,
         # sometimes the result is wrong (e.g. test_simple_fixed
         # fails).  If we call it by DynamicInvoke, the result is

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 28 10:32:56 2008
@@ -103,6 +103,28 @@
                                 annotatorpolicy=annotatorpolicy,
                                 nowrap=False)
 
+    def test_dump_assembly(self):
+        import os
+        from pypy.jit.codegen.cli import methodbuilder
+
+        # clear the global state, setup env
+        methodbuilder.assemblyData = methodbuilder.AssemblyData()
+        oldenv = os.environ.get('PYPYJITLOG')
+        os.environ['PYPYJITLOG'] = 'generated.dll'
+        try:
+            self.test_adder_compile()
+        finally:
+            # reset the global state, clear env
+            methodbuilder.assemblyData = methodbuilder.AssemblyData()
+            if oldenv:
+                os.environ['PYPYJITLOG'] = oldenv
+            else:
+                del os.environ['PYPYJITLOG']
+
+            f = py.path.local('generated.dll')
+            assert f.check()
+            f.remove()
+
     def test_largedummy_compile(self):
         py.test.skip('it works only if we increase .maxstack')
 

Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs
==============================================================================
--- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs	(original)
+++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs	Wed May 28 10:32:56 2008
@@ -3,6 +3,7 @@
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Runtime.Serialization;
 using System.IO;
+using System.Reflection;
 using System.Reflection.Emit;
 using pypy.runtime;
 
@@ -118,6 +119,54 @@
         }
     }
 
+    public class AutoSaveAssembly
+    {
+        private AssemblyBuilder assembly;
+        private string name;
+
+        public static AutoSaveAssembly Create(string name)
+        {
+            return new AutoSaveAssembly(name);
+        }
+
+        public AutoSaveAssembly(string name)
+        {
+            this.name = name;
+            AssemblyName assemblyName = new AssemblyName(); 
+            assemblyName.Name = name;
+            this.assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
+        }
+
+        ~AutoSaveAssembly()
+        {
+            this.assembly.Save(this.name);
+        }
+
+        public AssemblyBuilder GetAssemblyBuilder()
+        {
+            return this.assembly;
+        }
+
+        public static TypeBuilder DefineType(ModuleBuilder module, string name)
+        {
+            return module.DefineType(name,
+                                     TypeAttributes.Public |
+                                     TypeAttributes.Class);
+        }
+
+        public static MethodBuilder DefineMethod(TypeBuilder typeBuilder, string name, Type res, Type[] args)
+        {
+            return typeBuilder.DefineMethod("invoke",
+                                            MethodAttributes.HideBySig | 
+                                            MethodAttributes.Static | 
+                                            MethodAttributes.Public, 
+                                            res, 
+                                            args);
+        }
+
+        
+    }
+
     public class Utils
     {
         public static DynamicMethod CreateDynamicMethod(string name, Type res, Type[] args)



More information about the Pypy-commit mailing list