Author: Maciej Fijalkowski <[email protected]>
Branch: better-jit-hooks
Changeset: r51051:e7ce390271a7
Date: 2012-01-06 00:43 +0200
http://bitbucket.org/pypy/pypy/changeset/e7ce390271a7/
Log: fix pypyjit module, more work tomorrow
diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py
--- a/pypy/module/pypyjit/__init__.py
+++ b/pypy/module/pypyjit/__init__.py
@@ -7,8 +7,8 @@
interpleveldefs = {
'set_param': 'interp_jit.set_param',
'residual_call': 'interp_jit.residual_call',
- 'set_compile_hook': 'interp_jit.set_compile_hook',
- 'set_abort_hook': 'interp_jit.set_abort_hook',
+ 'set_compile_hook': 'interp_resop.set_compile_hook',
+ 'set_abort_hook': 'interp_resop.set_abort_hook',
'DebugMergePoint': 'interp_resop.W_DebugMergePoint',
}
diff --git a/pypy/module/pypyjit/interp_jit.py
b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -14,7 +14,6 @@
from pypy.interpreter.pyframe import PyFrame
from pypy.interpreter.pyopcode import ExitFrame
from opcode import opmap
-from pypy.rlib.nonconst import NonConstant
PyFrame._virtualizable2_ = ['last_instr', 'pycode',
'valuestackdepth', 'locals_stack_w[*]',
@@ -167,48 +166,3 @@
'''For testing. Invokes callable(...), but without letting
the JIT follow the call.'''
return space.call_args(w_callable, __args__)
-
-class Cache(object):
- in_recursion = False
-
- def __init__(self, space):
- self.w_compile_hook = space.w_None
- self.w_abort_hook = space.w_None
-
-def set_compile_hook(space, w_hook):
- """ set_compile_hook(hook)
-
- Set a compiling hook that will be called each time a loop is compiled.
- The hook will be called with the following signature:
- hook(merge_point_type, loop_type, greenkey or guard_number, operations)
-
- for now merge point type is always `main`
-
- loop_type can be either `loop` `entry_bridge` or `bridge`
- in case loop is not `bridge`, greenkey will be a set of constants
- for jit merge point. in case it's `main` it'll be a tuple
- (code, offset, is_being_profiled)
-
- Note that jit hook is not reentrant. It means that if the code
- inside the jit hook is itself jitted, it will get compiled, but the
- jit hook won't be called for that.
-
- XXX write down what else
- """
- cache = space.fromcache(Cache)
- cache.w_compile_hook = w_hook
- cache.in_recursion = NonConstant(False)
- return space.w_None
-
-def set_abort_hook(space, w_hook):
- """ set_abort_hook(hook)
-
- Set a hook (callable) that will be called each time there is tracing
- aborted due to some reason. The hook will be called with string describing
- the reason as an argument
- """
- cache = space.fromcache(Cache)
- cache.w_abort_hook = w_hook
- cache.in_recursion = NonConstant(False)
- return space.w_None
-
diff --git a/pypy/module/pypyjit/interp_resop.py
b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -7,8 +7,76 @@
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
from pypy.rpython.lltypesystem.rclass import OBJECT
from pypy.jit.metainterp.resoperation import rop
+from pypy.rlib.nonconst import NonConstant
-def wrap_oplist(space, logops, operations):
+
+class Cache(object):
+ in_recursion = False
+
+ def __init__(self, space):
+ self.w_compile_hook = space.w_None
+ self.w_abort_hook = space.w_None
+
+def wrap_greenkey(space, jitdriver, greenkey):
+ if jitdriver.name == 'pypyjit':
+ next_instr = greenkey[0].getint()
+ is_being_profiled = greenkey[1].getint()
+ ll_code = lltype.cast_opaque_ptr(lltype.Ptr(OBJECT),
+ greenkey[2].getref_base())
+ pycode = cast_base_ptr_to_instance(PyCode, ll_code)
+ return space.newtuple([space.wrap(pycode), space.wrap(next_instr),
+ space.newbool(is_being_profiled)])
+ else:
+ return space.wrap('who knows?')
+
+def set_compile_hook(space, w_hook):
+ """ set_compile_hook(hook)
+
+ Set a compiling hook that will be called each time a loop is compiled.
+ The hook will be called with the following signature:
+ hook(jitdriver_name, loop_type, greenkey or guard_number, operations,
+ assembler_addr, assembler_length)
+
+ jitdriver_name is the name of this particular jitdriver, 'pypyjit' is
+ the main interpreter loop
+
+ loop_type can be either `loop` `entry_bridge` or `bridge`
+ in case loop is not `bridge`, greenkey will be a tuple of constants
+ or a string describing it.
+
+ for the interpreter loop` it'll be a tuple
+ (code, offset, is_being_profiled)
+
+ assembler_addr is an integer describing where assembler starts,
+ can be accessed via ctypes, assembler_lenght is the lenght of compiled
+ asm
+
+ Note that jit hook is not reentrant. It means that if the code
+ inside the jit hook is itself jitted, it will get compiled, but the
+ jit hook won't be called for that.
+ """
+ cache = space.fromcache(Cache)
+ cache.w_compile_hook = w_hook
+ cache.in_recursion = NonConstant(False)
+ return space.w_None
+
+def set_abort_hook(space, w_hook):
+ """ set_abort_hook(hook)
+
+ Set a hook (callable) that will be called each time there is tracing
+ aborted due to some reason.
+
+ The hook will be called as in: hook(jitdriver_name, greenkey, reason)
+
+ Where reason is the reason for abort, see documentation for
set_compile_hook
+ for descriptions of other arguments.
+ """
+ cache = space.fromcache(Cache)
+ cache.w_abort_hook = w_hook
+ cache.in_recursion = NonConstant(False)
+ return space.w_None
+
+def wrap_oplist(space, logops, operations, ops_offset):
list_w = []
for op in operations:
if op.getopnum() == rop.DEBUG_MERGE_POINT:
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -1,10 +1,8 @@
from pypy.jit.codewriter.policy import JitPolicy
from pypy.rlib.jit import JitPortal
-from pypy.module.pypyjit.interp_jit import Cache
from pypy.interpreter.error import OperationError
from pypy.jit.metainterp.jitprof import counter_names
-from pypy.module.pypyjit.interp_resop import wrap_oplist
-from pypy.interpreter.pycode import PyCode
+from pypy.module.pypyjit.interp_resop import wrap_oplist, Cache, wrap_greenkey
class PyPyPortal(JitPortal):
def on_abort(self, reason, jitdriver, greenkey):
@@ -16,52 +14,43 @@
cache.in_recursion = True
try:
space.call_function(cache.w_abort_hook,
+ space.wrap(jitdriver.name),
+ wrap_greenkey(space, jitdriver, greenkey),
space.wrap(counter_names[reason]))
except OperationError, e:
e.write_unraisable(space, "jit hook ", cache.w_abort_hook)
cache.in_recursion = False
def on_compile(self, jitdriver, logger, looptoken, operations, type,
- greenkey, asmstart, asmlen):
- from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ greenkey, ops_offset, asmstart, asmlen):
+ self._compile_hook(jitdriver, logger, operations, type,
+ ops_offset, asmstart, asmlen,
+ wrap_greenkey(self.space, jitdriver, greenkey))
+ def on_compile_bridge(self, jitdriver, logger, orig_looptoken, operations,
+ n, ops_offset, asmstart, asmlen):
+ self._compile_hook(jitdriver, logger, operations, 'bridge',
+ ops_offset, asmstart, asmlen,
+ self.space.wrap(n))
+
+ def _compile_hook(self, jitdriver, logger, operations, type,
+ ops_offset, asmstart, asmlen, w_arg):
space = self.space
cache = space.fromcache(Cache)
if cache.in_recursion:
return
if space.is_true(cache.w_compile_hook):
logops = logger._make_log_operations()
- list_w = wrap_oplist(space, logops, operations)
- pycode = cast_base_ptr_to_instance(PyCode, ll_pycode)
+ list_w = wrap_oplist(space, logops, operations, ops_offset)
cache.in_recursion = True
try:
space.call_function(cache.w_compile_hook,
- space.wrap('main'),
+ space.wrap(jitdriver.name),
space.wrap(type),
- space.newtuple([pycode,
- space.wrap(next_instr),
- space.wrap(is_being_profiled)]),
- space.newlist(list_w))
- except OperationError, e:
- e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
- cache.in_recursion = False
-
- def on_compile_bridge(self, jitdriver, logger, orig_looptoken, operations,
- n, asm, asmlen):
- space = self.space
- cache = space.fromcache(Cache)
- if cache.in_recursion:
- return
- if space.is_true(cache.w_compile_hook):
- logops = logger._make_log_operations()
- list_w = wrap_oplist(space, logops, operations)
- cache.in_recursion = True
- try:
- space.call_function(cache.w_compile_hook,
- space.wrap('main'),
- space.wrap('bridge'),
- space.wrap(n),
- space.newlist(list_w))
+ w_arg,
+ space.newlist(list_w),
+ space.wrap(asmstart),
+ space.wrap(asmlen))
except OperationError, e:
e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
cache.in_recursion = False
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py
b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -44,11 +44,13 @@
greenkey = [ConstInt(0), ConstInt(0), ConstPtr(code_gcref)]
def interp_on_compile():
- pypyjitdriver.on_compile(logger, JitCellToken(), oplist, 'loop',
- 0, False, ll_code)
+ pypy_portal.on_compile(pypyjitdriver, logger, JitCellToken(),
+ oplist, 'loop', greenkey, {}, 0, 0)
def interp_on_compile_bridge():
- pypyjitdriver.on_compile_bridge(logger, JitCellToken(), oplist, 0)
+ pypy_portal.on_compile_bridge(pypyjitdriver, logger,
+ JitCellToken(), oplist, 0,
+ {}, 0, 0)
def interp_on_abort():
pypy_portal.on_abort(ABORT_TOO_LONG, pypyjitdriver, greenkey)
@@ -61,21 +63,21 @@
import pypyjit
all = []
- def hook(*args):
- assert args[0] == 'main'
- assert args[1] in ['loop', 'bridge']
- all.append(args[2:])
+ def hook(name, looptype, tuple_or_guard_no, ops, asmstart, asmlen):
+ all.append((name, looptype, tuple_or_guard_no, ops))
self.on_compile()
pypyjit.set_compile_hook(hook)
assert not all
self.on_compile()
assert len(all) == 1
- assert all[0][0][0].co_name == 'f'
- assert all[0][0][1] == 0
- assert all[0][0][2] == False
- assert len(all[0][1]) == 3
- assert 'int_add' in all[0][1][0]
+ elem = all[0]
+ assert elem[0] == 'pypyjit'
+ assert elem[2][0].co_name == 'f'
+ assert elem[2][1] == 0
+ assert elem[2][2] == False
+ assert len(elem[3]) == 3
+ assert 'int_add' in elem[3][0]
self.on_compile_bridge()
assert len(all) == 2
pypyjit.set_compile_hook(None)
@@ -136,9 +138,9 @@
import pypyjit
l = []
- def hook(reason):
- l.append(reason)
+ def hook(jitdriver_name, greenkey, reason):
+ l.append((jitdriver_name, reason))
pypyjit.set_abort_hook(hook)
self.on_abort()
- assert l == ['ABORT_TOO_LONG']
+ assert l == [('pypyjit', 'ABORT_TOO_LONG')]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit