[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