[pypy-svn] r71062 - in pypy/branch/oprofile-support/pypy/jit/backend/x86: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Feb 2 16:22:08 CET 2010


Author: cfbolz
Date: Tue Feb  2 16:22:08 2010
New Revision: 71062

Added:
   pypy/branch/oprofile-support/pypy/jit/backend/x86/profagent.py   (contents, props changed)
Modified:
   pypy/branch/oprofile-support/pypy/jit/backend/x86/assembler.py
   pypy/branch/oprofile-support/pypy/jit/backend/x86/test/test_assembler.py
Log:
Steps in the direction of nicely integrating profilers: add start/end_function
methods to MachineCodeBlockWrapper, which makes it give assembler address range
information to the profiler.


Modified: pypy/branch/oprofile-support/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/oprofile-support/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/oprofile-support/pypy/jit/backend/x86/assembler.py	Tue Feb  2 16:22:08 2010
@@ -13,7 +13,7 @@
      X86RegisterManager, X86XMMRegisterManager, get_ebp_ofs, FRAME_FIXED_SIZE,\
      FORCE_INDEX_OFS
 from pypy.rlib.objectmodel import we_are_translated, specialize
-from pypy.jit.backend.x86 import codebuf
+from pypy.jit.backend.x86 import codebuf, oprofile
 from pypy.jit.backend.x86.ri386 import *
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.backend.x86.support import values_array
@@ -35,18 +35,43 @@
 class MachineCodeBlockWrapper(object):
     MC_DEFAULT_SIZE = 1024*1024
 
-    def __init__(self, bigsize):
+    def __init__(self, bigsize, profile_agent=None):
         self.old_mcs = [] # keepalive
         self.bigsize = bigsize
-        self._mc = codebuf.MachineCodeBlock(bigsize)
+        self._mc = self._instantiate_mc()
+        self.function_name = None
+        self.profile_agent = profile_agent
+
+    def _instantiate_mc(self): # hook for testing
+        return codebuf.MachineCodeBlock(self.bigsize)
+
 
     def bytes_free(self):
-        return self._mc._size - self._mc._pos
+        return self._mc._size - self._mc.get_relative_pos()
+
+    def start_function(self, name):
+        self.function_name = name
+        self.start_pos = self._mc.get_relative_pos()
+
+    def end_function(self, done=True):
+        assert self.function_name is not None
+        size = self._mc.get_relative_pos() - self.start_pos
+        address = self.tell() - size
+        if self.profile_agent is not None:
+            self.profile_agent.native_code_written(self.function_name,
+                                                   address, size)
+        if done:
+            self.function_name = None
 
     def make_new_mc(self):
-        new_mc = codebuf.MachineCodeBlock(self.bigsize)
+        new_mc = self._instantiate_mc()
         debug_print('[new machine code block at', new_mc.tell(), ']')
         self._mc.JMP(rel32(new_mc.tell()))
+
+        if self.function_name is not None:
+            self.end_function(done=False)
+            self.start_pos = new_mc.get_relative_pos()
+
         self._mc.done()
         self.old_mcs.append(self._mc)
         self._mc = new_mc
@@ -69,7 +94,7 @@
     return method
 
 for name in dir(codebuf.MachineCodeBlock):
-    if name.upper() == name:
+    if name.upper() == name or name == "writechr":
         setattr(MachineCodeBlockWrapper, name, _new_method(name))
 
 class Assembler386(object):

Added: pypy/branch/oprofile-support/pypy/jit/backend/x86/profagent.py
==============================================================================
--- (empty file)
+++ pypy/branch/oprofile-support/pypy/jit/backend/x86/profagent.py	Tue Feb  2 16:22:08 2010
@@ -0,0 +1,12 @@
+
+class ProfileAgent(object):
+    """ A class that communicates to a profiler which assembler code belongs to
+    which functions. """
+
+    def startup(self):
+        pass
+    def shutdown(self):
+        pass
+    def native_code_written(self, name, address, size):
+        raise NotImplementedError
+

Modified: pypy/branch/oprofile-support/pypy/jit/backend/x86/test/test_assembler.py
==============================================================================
--- pypy/branch/oprofile-support/pypy/jit/backend/x86/test/test_assembler.py	(original)
+++ pypy/branch/oprofile-support/pypy/jit/backend/x86/test/test_assembler.py	Tue Feb  2 16:22:08 2010
@@ -1,5 +1,5 @@
 from pypy.jit.backend.x86.ri386 import *
-from pypy.jit.backend.x86.assembler import Assembler386
+from pypy.jit.backend.x86.assembler import Assembler386, MachineCodeBlockWrapper
 from pypy.jit.backend.x86.regalloc import X86FrameManager, get_ebp_ofs
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat
 from pypy.rlib.rarithmetic import intmask
@@ -11,10 +11,20 @@
     supports_floats = True
 
 class FakeMC:
-    def __init__(self):
+    def __init__(self, base_address=0):
         self.content = []
+        self._size = 100
+        self.base_address = base_address
     def writechr(self, n):
         self.content.append(n)
+    def tell(self):
+        return self.base_address + len(self.content)
+    def get_relative_pos(self):
+        return len(self.content)
+    def JMP(self, *args):
+        self.content.append(("JMP", args))
+    def done(self):
+        pass
 
 
 def test_write_failure_recovery_description():
@@ -233,3 +243,40 @@
         # an approximate result, it might mean that only the first 32
         # bits of the float were correctly saved and restored.
         assert assembler.fail_boxes_float.getitem(i) == expected_floats[i]
+
+class ProfileAgent(object):
+    def __init__(self):
+        self.functions = []
+
+    def native_code_written(self, name, address, size):
+        self.functions.append((name, address, size))
+
+class FakeMCWrapper(MachineCodeBlockWrapper):
+    count = 0
+    def _instantiate_mc(self):
+        self.count += 1
+        return FakeMC(200 * (self.count - 1))
+
+def test_mc_wrapper_profile_agent():
+    agent = ProfileAgent()
+    mc = FakeMCWrapper(100, agent)
+    mc.start_function("abc")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.end_function()
+    assert agent.functions == [("abc", 0, 4)]
+    mc.writechr("x")
+    mc.start_function("cde")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.writechr("x")
+    mc.end_function()
+    assert agent.functions == [("abc", 0, 4), ("cde", 5, 4)]
+    mc.start_function("xyz")
+    for i in range(50):
+        mc.writechr("x")
+    mc.end_function()
+    assert agent.functions == [("abc", 0, 4), ("cde", 5, 4), ("xyz", 9, 29), ("xyz", 200, 22)]



More information about the Pypy-commit mailing list