[pypy-commit] pypy better-jit-hooks: merged upstream

alex_gaynor noreply at buildbot.pypy.org
Sun Jan 8 19:54:33 CET 2012


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: better-jit-hooks
Changeset: r51142:ade5f6c6f404
Date: 2012-01-08 12:54 -0600
http://bitbucket.org/pypy/pypy/changeset/ade5f6c6f404/

Log:	merged upstream

diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -305,6 +305,13 @@
         show_procedures(metainterp_sd, loop)
         loop.check_consistency()
 
+    if metainterp_sd.warmrunnerdesc is not None:
+        portal = metainterp_sd.warmrunnerdesc.portal
+        portal.before_compile(jitdriver_sd.jitdriver, metainterp_sd.logger_ops,
+                              original_jitcell_token, loop.operations, type,
+                              greenkey)
+    else:
+        portal = None
     operations = get_deep_immutable_oplist(loop.operations)
     metainterp_sd.profiler.start_backend()
     debug_start("jit-backend")
@@ -316,11 +323,10 @@
     finally:
         debug_stop("jit-backend")
     metainterp_sd.profiler.end_backend()
-    if metainterp_sd.warmrunnerdesc is not None:
-        portal = metainterp_sd.warmrunnerdesc.portal
-        portal.on_compile(jitdriver_sd.jitdriver, metainterp_sd.logger_ops,
-                          original_jitcell_token, loop.operations, type,
-                          greenkey, ops_offset, asmstart, asmlen)
+    if portal is not None:
+        portal.after_compile(jitdriver_sd.jitdriver, metainterp_sd.logger_ops,
+                             original_jitcell_token, loop.operations, type,
+                             greenkey, ops_offset, asmstart, asmlen)
     metainterp_sd.stats.add_new_loop(loop)
     if not we_are_translated():
         metainterp_sd.stats.compiled()
@@ -341,8 +347,15 @@
         show_procedures(metainterp_sd)
         seen = dict.fromkeys(inputargs)
         TreeLoop.check_consistency_of_branch(operations, seen)
+    if metainterp_sd.warmrunnerdesc is not None:
+        portal = metainterp_sd.warmrunnerdesc.portal
+        portal.before_compile_bridge(jitdriver_sd.jitdriver,
+                                     metainterp_sd.logger_ops,
+                                     original_loop_token, operations, n)
+    else:
+        portal = None
+    operations = get_deep_immutable_oplist(operations)
     metainterp_sd.profiler.start_backend()
-    operations = get_deep_immutable_oplist(operations)
     debug_start("jit-backend")
     try:
         tp = metainterp_sd.cpu.compile_bridge(faildescr, inputargs, operations,
@@ -351,12 +364,12 @@
     finally:
         debug_stop("jit-backend")
     metainterp_sd.profiler.end_backend()
-    if metainterp_sd.warmrunnerdesc is not None:
-        portal = metainterp_sd.warmrunnerdesc.portal
-        portal.on_compile_bridge(jitdriver_sd.jitdriver,
-                                 metainterp_sd.logger_ops,
-                                 original_loop_token, operations, n, ops_offset,
-                                 asmstart, asmlen)
+    if portal is not None:
+        portal.after_compile_bridge(jitdriver_sd.jitdriver,
+                                    metainterp_sd.logger_ops,
+                                    original_loop_token, operations, n,
+                                    ops_offset,
+                                    asmstart, asmlen)
     if not we_are_translated():
         metainterp_sd.stats.compiled()
     metainterp_sd.log("compiled new bridge")
diff --git a/pypy/jit/metainterp/test/test_jitportal.py b/pypy/jit/metainterp/test/test_jitportal.py
--- a/pypy/jit/metainterp/test/test_jitportal.py
+++ b/pypy/jit/metainterp/test/test_jitportal.py
@@ -5,6 +5,7 @@
 from pypy.jit.codewriter.policy import JitPolicy
 from pypy.jit.metainterp.jitprof import ABORT_FORCE_QUASIIMMUT
 from pypy.jit.metainterp.resoperation import rop
+from pypy.rpython.annlowlevel import hlstr
 
 class TestJitPortal(LLJitMixin):
     def test_abort_quasi_immut(self):
@@ -41,14 +42,25 @@
         assert reasons == [ABORT_FORCE_QUASIIMMUT] * 2
 
     def test_on_compile(self):
-        called = {}
+        called = []
         
         class MyJitPortal(JitPortal):
-            def on_compile(self, jitdriver, logger, looptoken, operations,
-                           type, greenkey, ops_offset, asmaddr, asmlen):
+            def after_compile(self, jitdriver, logger, looptoken, operations,
+                              type, greenkey, ops_offset, asmaddr, asmlen):
                 assert asmaddr == 0
                 assert asmlen == 0
-                called[(greenkey[1].getint(), greenkey[0].getint(), type)] = looptoken
+                called.append(("compile", greenkey[1].getint(),
+                               greenkey[0].getint(), type))
+
+            def before_compile(self, jitdriver, logger, looptoken, oeprations,
+                               type, greenkey):
+                called.append(("optimize", greenkey[1].getint(),
+                               greenkey[0].getint(), type))
+
+            def before_optimize(self, jitdriver, logger, looptoken, oeprations,
+                               type, greenkey):
+                called.append(("trace", greenkey[1].getint(),
+                               greenkey[0].getint(), type))
 
         portal = MyJitPortal()
 
@@ -62,26 +74,35 @@
                 i += 1
 
         self.meta_interp(loop, [1, 4], policy=JitPolicy(portal))
-        assert sorted(called.keys()) == [(4, 1, "loop")]
+        assert called == [#("trace", 4, 1, "loop"),
+                          ("optimize", 4, 1, "loop"),
+                          ("compile", 4, 1, "loop")]
         self.meta_interp(loop, [2, 4], policy=JitPolicy(portal))
-        assert sorted(called.keys()) == [(4, 1, "loop"),
-                                         (4, 2, "loop")]
+        assert called == [#("trace", 4, 1, "loop"),
+                          ("optimize", 4, 1, "loop"),
+                          ("compile", 4, 1, "loop"),
+                          #("trace", 4, 2, "loop"),
+                          ("optimize", 4, 2, "loop"),
+                          ("compile", 4, 2, "loop")]
 
     def test_on_compile_bridge(self):
-        called = {}
+        called = []
         
         class MyJitPortal(JitPortal):
-            def on_compile(self, jitdriver, logger, looptoken, operations,
+            def after_compile(self, jitdriver, logger, looptoken, operations,
                            type, greenkey, ops_offset, asmaddr, asmlen):
                 assert asmaddr == 0
                 assert asmlen == 0
-                called[(greenkey[1].getint(), greenkey[0].getint(), type)] = looptoken
+                called.append("compile")
 
-            def on_compile_bridge(self, jitdriver, logger, orig_token,
-                                  operations, n, ops_offset, asmstart, asmlen):
-                assert 'bridge' not in called
-                called['bridge'] = orig_token
+            def after_compile_bridge(self, jitdriver, logger, orig_token,
+                                     operations, n, ops_offset, asmstart, asmlen):
+                called.append("compile_bridge")
 
+            def before_compile_bridge(self, jitdriver, logger, orig_token,
+                                     operations, n):
+                called.append("before_compile_bridge")
+            
         driver = JitDriver(greens = ['n', 'm'], reds = ['i'])
 
         def loop(n, m):
@@ -94,7 +115,7 @@
                 i += 1
 
         self.meta_interp(loop, [1, 10], policy=JitPolicy(MyJitPortal()))
-        assert sorted(called.keys()) == ['bridge', (10, 1, "loop")]
+        assert called == ["compile", "before_compile_bridge", "compile_bridge"]
 
     def test_resop_interface(self):
         driver = JitDriver(greens = [], reds = ['i'])
@@ -110,7 +131,18 @@
                                      [jit_hooks.boxint_new(3),
                                       jit_hooks.boxint_new(4)],
                                      jit_hooks.boxint_new(1))
-            return jit_hooks.resop_opnum(op)
+            assert hlstr(jit_hooks.resop_getopname(op)) == 'int_add'
+            assert jit_hooks.resop_getopnum(op) == rop.INT_ADD
+            box = jit_hooks.resop_getarg(op, 0)
+            assert jit_hooks.box_getint(box) == 3
+            box2 = jit_hooks.box_clone(box)
+            assert box2 != box
+            assert jit_hooks.box_getint(box2) == 3
+            assert not jit_hooks.box_isconst(box2)
+            box3 = jit_hooks.box_constbox(box)
+            assert jit_hooks.box_getint(box) == 3
+            assert jit_hooks.box_isconst(box3)
+            box4 = jit_hooks.box_nonconstbox(box)
+            assert not jit_hooks.box_isconst(box4)
 
-        res = self.meta_interp(main, [])
-        assert res == rop.INT_ADD
+        self.meta_interp(main, [])
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
@@ -8,8 +8,10 @@
         'set_param':    'interp_jit.set_param',
         'residual_call': 'interp_jit.residual_call',
         'set_compile_hook': 'interp_resop.set_compile_hook',
+        'set_optimize_hook': 'interp_resop.set_optimize_hook',
         'set_abort_hook': 'interp_resop.set_abort_hook',
         'ResOperation': 'interp_resop.WrappedOp',
+        'Box': 'interp_resop.WrappedBox',
     }
 
     def setup_after_space_initialization(self):
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
@@ -5,7 +5,7 @@
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance, hlstr
 from pypy.rpython.lltypesystem.rclass import OBJECT
 from pypy.jit.metainterp.resoperation import rop, AbstractResOp
 from pypy.rlib.nonconst import NonConstant
@@ -61,6 +61,37 @@
     cache.in_recursion = NonConstant(False)
     return space.w_None
 
+def set_optimize_hook(space, w_hook):
+    """ set_compile_hook(hook)
+
+    Set a compiling hook that will be called each time a loop is optimized,
+    but before assembler compilation. This allows to add additional
+    optimizations on Python level.
+    
+    The hook will be called with the following signature:
+    hook(jitdriver_name, loop_type, greenkey or guard_number, operations)
+
+    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)
+
+    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.
+
+    Result value will be the resulting list of operations, or None
+    """
+    cache = space.fromcache(Cache)
+    cache.w_optimize_hook = w_hook
+    cache.in_recursion = NonConstant(False)
+    return space.w_None
+
 def set_abort_hook(space, w_hook):
     """ set_abort_hook(hook)
 
@@ -83,14 +114,12 @@
                       logops.repr_of_resop(op)) for op in operations]
 
 @unwrap_spec(num=int, offset=int, repr=str)
-def descr_new_resop(space, w_tp, num, w_args, w_res=NoneNotWrapped, offset=-1,
+def descr_new_resop(space, w_tp, num, w_args, w_res=None, offset=-1,
                     repr=''):
-    args = [jit_hooks.boxint_new(space.int_w(w_arg)) for w_arg in
+    args = [space.interp_w(WrappedBox, w_arg).llbox for w_arg in
             space.listview(w_args)]
-    if w_res is None:
-        llres = lltype.nullptr(llmemory.GCREF.TO)
-    else:
-        llres = jit_hooks.boxint_new(space.int_w(w_res))
+    llres = space.interp_w(WrappedBox, w_res).llbox
+    # XXX None case
     return WrappedOp(jit_hooks.resop_new(num, args, llres), offset, repr)
 
 class WrappedOp(Wrappable):
@@ -105,7 +134,14 @@
         return space.wrap(self.repr_of_resop)
 
     def descr_num(self, space):
-        return space.wrap(jit_hooks.resop_opnum(self.op))
+        return space.wrap(jit_hooks.resop_getopnum(self.op))
+
+    def descr_name(self, space):
+        return space.wrap(hlstr(jit_hooks.resop_getopname(self.op)))
+
+    @unwrap_spec(no=int)
+    def descr_getarg(self, space, no):
+        return WrappedBox(jit_hooks.resop_getarg(self.op, no))
 
 WrappedOp.typedef = TypeDef(
     'ResOperation',
@@ -113,5 +149,26 @@
     __new__ = interp2app(descr_new_resop),
     __repr__ = interp2app(WrappedOp.descr_repr),
     num = GetSetProperty(WrappedOp.descr_num),
+    name = GetSetProperty(WrappedOp.descr_name),
+    getarg = interp2app(WrappedOp.descr_getarg),
 )
 WrappedOp.acceptable_as_base_class = False
+
+class WrappedBox(Wrappable):
+    """ A class representing a single box
+    """
+    def __init__(self, llbox):
+        self.llbox = llbox
+
+    def descr_getint(self, space):
+        return space.wrap(jit_hooks.box_getint(self.llbox))
+
+ at unwrap_spec(no=int)
+def descr_new_box(space, w_tp, no):
+    return WrappedBox(jit_hooks.boxint_new(no))
+
+WrappedBox.typedef = TypeDef(
+    'Box',
+    __new__ = interp2app(descr_new_box),
+    getint = interp2app(WrappedBox.descr_getint),
+)
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,8 +1,10 @@
 from pypy.jit.codewriter.policy import JitPolicy
 from pypy.rlib.jit import JitPortal
+from pypy.rlib import jit_hooks
 from pypy.interpreter.error import OperationError
 from pypy.jit.metainterp.jitprof import counter_names
-from pypy.module.pypyjit.interp_resop import wrap_oplist, Cache, wrap_greenkey
+from pypy.module.pypyjit.interp_resop import wrap_oplist, Cache, wrap_greenkey,\
+     WrappedOp
 
 class PyPyPortal(JitPortal):
     def on_abort(self, reason, jitdriver, greenkey):
@@ -21,18 +23,28 @@
                 e.write_unraisable(space, "jit hook ", cache.w_abort_hook)
             cache.in_recursion = False
 
-    def on_compile(self, jitdriver, logger, looptoken, operations, type,
-                   greenkey, ops_offset, asmstart, asmlen):
+    def after_compile(self, jitdriver, logger, looptoken, operations, type,
+                      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):
+    def after_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 before_compile(self, jitdriver, logger, looptoken, operations, type,
+                      greenkey):
+        self._optimize_hook(jitdriver, logger, operations, type,
+                            wrap_greenkey(self.space, jitdriver, greenkey))
+
+    def before_compile_bridge(self, jitdriver, logger, orig_looptoken,
+                              operations, n):
+        self._optimize_hook(jitdriver, logger, operations, 'bridge',
+                           self.space.wrap(n))
+
     def _compile_hook(self, jitdriver, logger, operations, type,
                       ops_offset, asmstart, asmlen, w_arg):
         space = self.space
@@ -55,6 +67,34 @@
                 e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
             cache.in_recursion = False
 
+    def _optimize_hook(self, jitdriver, logger, operations, type, w_arg):
+        space = self.space
+        cache = space.fromcache(Cache)
+        if cache.in_recursion:
+            return
+        if space.is_true(cache.w_optimize_hook):
+            logops = logger._make_log_operations()
+            list_w = wrap_oplist(space, logops, operations, {})
+            cache.in_recursion = True
+            try:
+                w_res = space.call_function(cache.w_optimize_hook,
+                                            space.wrap(jitdriver.name),
+                                            space.wrap(type),
+                                            w_arg,
+                                            space.newlist(list_w))
+                if space.is_w(w_res, space.w_None):
+                    return
+                l = []
+                for w_item in space.listview(w_res):
+                    item = space.interp_w(WrappedOp, w_item)
+                    l.append(jit_hooks._cast_to_resop(item.op))
+                operations[:] = l # modifying operations above is probably not
+                # a great idea since types may not work and we'll end up with
+                # half-working list and a segfault/fatal RPython error
+            except OperationError, e:
+                e.write_unraisable(space, "jit hook ", cache.w_compile_hook)
+            cache.in_recursion = False
+
 pypy_portal = PyPyPortal()
 
 class PyPyJitPolicy(JitPolicy):
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
@@ -47,27 +47,32 @@
         code_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, ll_code)
         logger = Logger(MockSD())
 
-        oplist = parse("""
-        [i1, i2]
+        cls.origoplist = parse("""
+        [i1, i2, p2]
         i3 = int_add(i1, i2)
         debug_merge_point(0, 0, 0, 0, ConstPtr(ptr0))
+        guard_nonnull(p2) []
         guard_true(i3) []
         """, namespace={'ptr0': code_gcref}).operations
         greenkey = [ConstInt(0), ConstInt(0), ConstPtr(code_gcref)]
         offset = {}
-        for i, op in enumerate(oplist):
+        for i, op in enumerate(cls.origoplist):
             if i != 1:
                offset[op] = i
 
         def interp_on_compile():
-            pypy_portal.on_compile(pypyjitdriver, logger, JitCellToken(),
-                                   oplist, 'loop', greenkey, offset,
-                                   0, 0)
+            pypy_portal.after_compile(pypyjitdriver, logger, JitCellToken(),
+                                      cls.oplist, 'loop', greenkey, offset,
+                                      0, 0)
 
         def interp_on_compile_bridge():
-            pypy_portal.on_compile_bridge(pypyjitdriver, logger,
-                                          JitCellToken(), oplist, 0,
-                                          offset, 0, 0)
+            pypy_portal.after_compile_bridge(pypyjitdriver, logger,
+                                             JitCellToken(), cls.oplist, 0,
+                                             offset, 0, 0)
+
+        def interp_on_optimize():
+            pypy_portal.before_compile(pypyjitdriver, logger, JitCellToken(),
+                                       cls.oplist, 'loop', greenkey)
 
         def interp_on_abort():
             pypy_portal.on_abort(ABORT_TOO_LONG, pypyjitdriver, greenkey)
@@ -76,6 +81,10 @@
         cls.w_on_compile_bridge = space.wrap(interp2app(interp_on_compile_bridge))
         cls.w_on_abort = space.wrap(interp2app(interp_on_abort))
         cls.w_int_add_num = space.wrap(rop.INT_ADD)
+        cls.w_on_optimize = space.wrap(interp2app(interp_on_optimize))
+
+    def setup_method(self, meth):
+        self.__class__.oplist = self.origoplist
 
     def test_on_compile(self):
         import pypyjit
@@ -94,7 +103,7 @@
         assert elem[2][0].co_name == 'function'
         assert elem[2][1] == 0
         assert elem[2][2] == False
-        assert len(elem[3]) == 3
+        assert len(elem[3]) == 4
         int_add = elem[3][0]
         #assert int_add.name == 'int_add'
         assert int_add.num == self.int_add_num
@@ -160,8 +169,27 @@
         self.on_abort()
         assert l == [('pypyjit', 'ABORT_TOO_LONG')]
 
+    def test_on_optimize(self):
+        import pypyjit
+        l = []
+
+        def hook(name, looptype, tuple_or_guard_no, ops, *args):
+            l.append(ops)
+
+        def optimize_hook(name, looptype, tuple_or_guard_no, ops):
+            return []
+
+        pypyjit.set_compile_hook(hook)
+        pypyjit.set_optimize_hook(optimize_hook)
+        self.on_optimize()
+        self.on_compile()
+        assert l == [[]]
+
     def test_creation(self):
-        import pypyjit
+        from pypyjit import Box, ResOperation
 
-        op = pypyjit.ResOperation(self.int_add_num, [1, 3], 4)
+        op = ResOperation(self.int_add_num, [Box(1), Box(3)], Box(4))
         assert op.num == self.int_add_num
+        assert op.name == 'int_add'
+        box = op.getarg(0)
+        assert box.getint() == 1
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -731,29 +731,62 @@
     like JIT loops compiled, aborts etc.
     An instance of this class might be returned by the policy.get_jit_portal
     method in order to function.
+
+    each hook will accept some of the following args:
+
+    
+    greenkey - a list of green boxes
+    jitdriver - an instance of jitdriver where tracing started
+    logger - an instance of jit.metainterp.logger.LogOperations
+    ops_offset
+    asmaddr - (int) raw address of assembler block
+    asmlen - assembler block length
+    type - either 'loop' or 'entry bridge'    
     """
     def on_abort(self, reason, jitdriver, greenkey):
         """ A hook called each time a loop is aborted with jitdriver and
         greenkey where it started, reason is a string why it got aborted
         """
 
-    def on_compile(self, jitdriver, logger, looptoken, operations, type,
-                   greenkey, ops_offset, asmaddr, asmlen):
-        """ A hook called when loop is compiled. Overwrite
-        for your own jitdriver if you want to do something special, like
-        call applevel code.
+    #def before_optimize(self, jitdriver, logger, looptoken, operations,
+    #                    type, greenkey):
+    #    """ A hook called before optimizer is run, args described in class
+    #    docstring. Overwrite for custom behavior
+    #    """
+    # DISABLED
 
-        jitdriver - an instance of jitdriver where tracing started
-        logger - an instance of jit.metainterp.logger.LogOperations
-        asmaddr - (int) raw address of assembler block
-        asmlen - assembler block length
-        type - either 'loop' or 'entry bridge'
+    def before_compile(self, jitdriver, logger, looptoken, operations, type,
+                       greenkey):
+        """ A hook called after a loop is optimized, before compiling assembler,
+        args described ni class docstring. Overwrite for custom behavior
         """
 
-    def on_compile_bridge(self, jitdriver, logger, orig_looptoken, operations,
-                          fail_descr_no, ops_offset, asmaddr, asmlen):
-        """ A hook called when a bridge is compiled. Overwrite
-        for your own jitdriver if you want to do something special
+    def after_compile(self, jitdriver, logger, looptoken, operations, type,
+                      greenkey, ops_offset, asmaddr, asmlen):
+        """ A hook called after a loop has compiled assembler,
+        args described in class docstring. Overwrite for custom behavior
+        """
+
+    #def before_optimize_bridge(self, jitdriver, logger, orig_looptoken,
+    #                           operations, fail_descr_no):
+    #    """ A hook called before a bridge is optimized.
+    #    Args described in class docstring, Overwrite for
+    #    custom behavior
+    #    """
+    # DISABLED
+
+    def before_compile_bridge(self, jitdriver, logger, orig_looptoken,
+                              operations, fail_descr_no):
+        """ A hook called before a bridge is compiled, but after optimizations
+        are performed. Args described in class docstring, Overwrite for
+        custom behavior
+        """
+
+    def after_compile_bridge(self, jitdriver, logger, orig_looptoken,
+                             operations, fail_descr_no, ops_offset, asmaddr,
+                             asmlen):
+        """ A hook called after a bridge is compiled, args described in class
+        docstring, Overwrite for custom behavior
         """
 
     def get_stats(self):
diff --git a/pypy/rlib/jit_hooks.py b/pypy/rlib/jit_hooks.py
--- a/pypy/rlib/jit_hooks.py
+++ b/pypy/rlib/jit_hooks.py
@@ -4,26 +4,28 @@
 from pypy.rpython.lltypesystem import llmemory, lltype
 from pypy.rpython.lltypesystem import rclass
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr,\
-     cast_base_ptr_to_instance
+     cast_base_ptr_to_instance, llstr, hlstr
 from pypy.rlib.objectmodel import specialize
 
-def register_helper(helper, s_result):
-    
-    class Entry(ExtRegistryEntry):
-        _about_ = helper
+def register_helper(s_result):
+    def wrapper(helper):
+        class Entry(ExtRegistryEntry):
+            _about_ = helper
 
-        def compute_result_annotation(self, *args):
-            return s_result
+            def compute_result_annotation(self, *args):
+                return s_result
 
-        def specialize_call(self, hop):
-            from pypy.rpython.lltypesystem import lltype
+            def specialize_call(self, hop):
+                from pypy.rpython.lltypesystem import lltype
 
-            c_func = hop.inputconst(lltype.Void, helper)
-            c_name = hop.inputconst(lltype.Void, 'access_helper')
-            args_v = [hop.inputarg(arg, arg=i)
-                      for i, arg in enumerate(hop.args_r)]
-            return hop.genop('jit_marker', [c_name, c_func] + args_v,
-                             resulttype=hop.r_result)
+                c_func = hop.inputconst(lltype.Void, helper)
+                c_name = hop.inputconst(lltype.Void, 'access_helper')
+                args_v = [hop.inputarg(arg, arg=i)
+                          for i, arg in enumerate(hop.args_r)]
+                return hop.genop('jit_marker', [c_name, c_func] + args_v,
+                                 resulttype=hop.r_result)
+        return helper
+    return wrapper
 
 def _cast_to_box(llref):
     from pypy.jit.metainterp.history import AbstractValue
@@ -42,6 +44,7 @@
     return lltype.cast_opaque_ptr(llmemory.GCREF,
                                   cast_instance_to_base_ptr(obj))
 
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
 def resop_new(no, llargs, llres):
     from pypy.jit.metainterp.history import ResOperation
 
@@ -49,15 +52,40 @@
     res = _cast_to_box(llres)
     return _cast_to_gcref(ResOperation(no, args, res))
 
-register_helper(resop_new, annmodel.SomePtr(llmemory.GCREF))
-
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
 def boxint_new(no):
     from pypy.jit.metainterp.history import BoxInt
     return _cast_to_gcref(BoxInt(no))
 
-register_helper(boxint_new, annmodel.SomePtr(llmemory.GCREF))
-
-def resop_opnum(llop):
+ at register_helper(annmodel.SomeInteger())
+def resop_getopnum(llop):
     return _cast_to_resop(llop).getopnum()
 
-register_helper(resop_opnum, annmodel.SomeInteger())
+ at register_helper(annmodel.SomeString(can_be_None=True))
+def resop_getopname(llop):
+    return llstr(_cast_to_resop(llop).getopname())
+
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
+def resop_getarg(llop, no):
+    return _cast_to_gcref(_cast_to_resop(llop).getarg(no))
+
+ at register_helper(annmodel.SomeInteger())
+def box_getint(llbox):
+    return _cast_to_box(llbox).getint()
+
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
+def box_clone(llbox):
+    return _cast_to_gcref(_cast_to_box(llbox).clonebox())
+
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
+def box_constbox(llbox):
+    return _cast_to_gcref(_cast_to_box(llbox).constbox())
+
+ at register_helper(annmodel.SomePtr(llmemory.GCREF))
+def box_nonconstbox(llbox):
+    return _cast_to_gcref(_cast_to_box(llbox).nonconstbox())
+
+ at register_helper(annmodel.SomeBool())
+def box_isconst(llbox):
+    from pypy.jit.metainterp.history import Const
+    return isinstance(_cast_to_box(llbox), Const)


More information about the pypy-commit mailing list