[pypy-commit] pypy default: Kill callback_hook. Replace it with a simpler and more explicit solution, which is to decorate

arigo noreply at buildbot.pypy.org
Sun Jan 13 16:37:26 CET 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r60030:6ce8443ec9eb
Date: 2013-01-13 15:33 +0100
http://bitbucket.org/pypy/pypy/changeset/6ce8443ec9eb/

Log:	Kill callback_hook. Replace it with a simpler and more explicit
	solution, which is to decorate explicitly the callbacks that you
	want the JIT to treat specially.

	Btw, another potential use of this would be to have the JIT see some
	function which is deep inside @dont_look_inside code, but which
	causes more app-level Python code to be invoked. This can be
	useful, to let the JIT see a bit more than just the app-level Python
	code (e.g. the wrapping of arguments).

diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -536,44 +536,6 @@
         self.check_trace_count(1)
 
 
-    def test_callback_jit_merge_point(self):
-        from pypy.rlib.objectmodel import register_around_callback_hook
-        from pypy.rpython.lltypesystem import lltype, rffi
-        from pypy.translator.tool.cbuild import ExternalCompilationInfo
-        
-        callback_jit_driver = JitDriver(greens = ['name'], reds = 'auto')
-        
-        def callback_merge_point(name):
-            callback_jit_driver.jit_merge_point(name=name)
-    
-        @callback_jit_driver.inline(callback_merge_point)
-        def callback_hook(name):
-            pass
-
-        def callback(a, b):
-            if a > b:
-                return 1
-            return -1
-
-        CB_TP = rffi.CCallback([lltype.Signed, lltype.Signed], lltype.Signed)
-        eci = ExternalCompilationInfo(includes=['stdlib.h'])
-        qsort = rffi.llexternal('qsort',
-                                [rffi.VOIDP, lltype.Signed, lltype.Signed,
-                                 CB_TP], lltype.Void, compilation_info=eci)
-        ARR = rffi.CArray(lltype.Signed)
-
-        def main():
-            register_around_callback_hook(callback_hook)
-            raw = lltype.malloc(ARR, 10, flavor='raw')
-            for i in range(10):
-                raw[i] = 10 - i
-            qsort(raw, 10, rffi.sizeof(lltype.Signed), callback)
-            lltype.free(raw, flavor='raw')
-
-        self.meta_interp(main, [])
-        self.check_trace_count(1)
-
-
 class TestLLWarmspot(WarmspotTests, LLJitMixin):
     CPUClass = runner.LLGraphCPU
     type_system = 'lltype'
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -152,6 +152,7 @@
 
 STDERR = 2
 
+ at jit.jit_callback("CFFI")
 def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
     """ Callback specification.
     ffi_cif - something ffi specific, don't care
@@ -201,4 +202,3 @@
         callback.write_error_return_value(ll_res)
     if ec is not None:
         cerrno.restore_errno_from(ec)
-invoke_callback._callback_hook_ = "CFFI"
diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.error import OperationError
-from pypy.rlib import rgc
+from pypy.rlib import rgc, jit
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -288,6 +288,7 @@
         post_code = ''
 
     src = py.code.Source("""
+    @jit.jit_callback('XML:%(name)s')
     def %(name)s_callback(%(first_arg)s, %(args)s):
         id = rffi.cast(lltype.Signed, %(ll_id)s)
         userdata = global_storage.get_object(id)
@@ -312,7 +313,6 @@
     """ % locals())
 
     exec str(src)
-    callback._callback_hook_ = "XML_" + name
 
     c_name = 'XML_Set' + name
     callback_type = lltype.Ptr(lltype.FuncType(
@@ -341,7 +341,6 @@
     else:
         result = 1
     return rffi.cast(rffi.INT, result)
-UnknownEncodingHandlerData_callback._callback_hook_ = None    # no jit needed
 callback_type = lltype.Ptr(lltype.FuncType(
     [rffi.VOIDP, rffi.CCHARP, XML_Encoding_Ptr], rffi.INT))
 XML_SetUnknownEncodingHandler = expat_external(
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
@@ -6,7 +6,7 @@
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside
-from pypy.rlib import jit, objectmodel
+from pypy.rlib import jit
 from pypy.rlib.jit import current_trace_length, unroll_parameters
 import pypy.interpreter.pyopcode   # for side-effects
 from pypy.interpreter.error import OperationError, operationerrfmt
@@ -97,15 +97,6 @@
                                     is_being_profiled=self.is_being_profiled)
         return jumpto
 
-callback_jit_driver = JitDriver(greens = ['name'], reds = 'auto')
-
-def callback_merge_point(name):
-    callback_jit_driver.jit_merge_point(name=name)
-
- at callback_jit_driver.inline(callback_merge_point)
-def callback_hook(name):
-    pass
-
 def _get_adapted_tick_counter():
     # Normally, the tick counter is decremented by 100 for every
     # Python opcode.  Here, to better support JIT compilation of
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -421,6 +421,7 @@
                                    hints={'callback':True}))
 
 
+ at jit.jit_callback("CLIBFFI")
 def ll_callback(ffi_cif, ll_res, ll_args, ll_userdata):
     """ Callback specification.
     ffi_cif - something ffi specific, don't care
@@ -431,7 +432,6 @@
     """
     userdata = rffi.cast(USERDATA_P, ll_userdata)
     userdata.callback(ll_args, ll_res, userdata)
-ll_callback._callback_hook_ = "CLIBFFI"
 
 class StackCheckError(ValueError):
     message = None
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -302,6 +302,32 @@
     pass
 
 
+def jit_callback(name):
+    """Use as a decorator for C callback functions, to insert a
+    jitdriver.jit_merge_point() at the start.  Only for callbacks
+    that typically invoke more app-level Python code.
+    """
+    def decorate(func):
+        from pypy.tool.sourcetools import compile2
+        #
+        def get_printable_location():
+            return name
+        jitdriver = JitDriver(get_printable_location=get_printable_location,
+                              greens=[], reds='auto', name=name)
+        #
+        args = ','.join(['a%d' % i for i in range(func.func_code.co_argcount)])
+        source = """def callback_with_jitdriver(%(args)s):
+                        jitdriver.jit_merge_point()
+                        return real_callback(%(args)s)""" % locals()
+        miniglobals = {
+            'jitdriver': jitdriver,
+            'real_callback': func,
+            }
+        exec compile2(source) in miniglobals
+        return miniglobals['callback_with_jitdriver']
+    return decorate
+
+
 # ____________________________________________________________
 # VRefs
 
@@ -458,9 +484,8 @@
             self.autoreds = True
             self.reds = []
             self.numreds = None # see warmspot.autodetect_jit_markers_redvars
-            for hook in (get_jitcell_at, set_jitcell_at, get_printable_location,
-                         confirm_enter_jit):
-                assert hook is None, "reds='auto' is not compatible with JitDriver hooks"
+            assert confirm_enter_jit is None, (
+                "reds='auto' is not compatible with confirm_enter_jit")
         else:
             if reds is not None:
                 self.reds = reds
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -595,16 +595,6 @@
     llhelper(rffi.AroundFnPtr, before)
     llhelper(rffi.AroundFnPtr, after)
 
-def register_around_callback_hook(hook):
-    """ Register a hook that's called before a callback from C calls RPython.
-    Primary usage is for JIT to have 'started from' hook.
-    """
-    from pypy.rpython.lltypesystem import rffi
-    from pypy.rpython.annlowlevel import llhelper
-   
-    rffi.aroundstate.callback_hook = hook
-    llhelper(rffi.CallbackHookPtr, hook)
-
 def is_in_callback():
     from pypy.rpython.lltypesystem import rffi
     return rffi.stackcounter.stacks_counter > 1
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -1,6 +1,6 @@
 import py
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lltype, rstr
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem import ll2ctypes
 from pypy.rpython.lltypesystem.llmemory import cast_ptr_to_adr
 from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy
@@ -13,7 +13,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython.tool.rfficache import platform, sizeof_c_type
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.rpython.annlowlevel import llhelper, llstr
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
 from pypy.rlib import jit
@@ -280,18 +280,7 @@
     if callbackholder is not None:
         callbackholder.callbacks[callable] = True
     args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))])
-    invoke_hook = getattr(callable, '_callback_hook_', None)
-    assert invoke_hook is None or isinstance(invoke_hook, str)
-
     source = py.code.Source(r"""
-        def inner_wrapper(%(args)s):
-            if invoke_hook is not None and aroundstate is not None:
-                callback_hook = aroundstate.callback_hook
-                if callback_hook:
-                    callback_hook(llstr(invoke_hook))
-            return callable(%(args)s)
-        inner_wrapper._never_inline_ = True
-        
         def wrapper(%(args)s):    # no *args - no GIL for mallocing the tuple
             llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
             if aroundstate is not None:
@@ -301,7 +290,7 @@
             # from now on we hold the GIL
             stackcounter.stacks_counter += 1
             try:
-                result = inner_wrapper(%(args)s)
+                result = callable(%(args)s)
             except Exception, e:
                 os.write(2,
                     "Warning: uncaught exception in callback: %%s %%s\n" %%
@@ -323,7 +312,6 @@
     miniglobals = locals().copy()
     miniglobals['Exception'] = Exception
     miniglobals['os'] = os
-    miniglobals['llstr'] = llstr
     miniglobals['we_are_translated'] = we_are_translated
     miniglobals['stackcounter'] = stackcounter
     exec source.compile() in miniglobals
@@ -331,11 +319,8 @@
 _make_wrapper_for._annspecialcase_ = 'specialize:memo'
 
 AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void))
-CallbackHookPtr = lltype.Ptr(lltype.FuncType([lltype.Ptr(rstr.STR)], lltype.Void))
 
 class AroundState:
-    callback_hook = None
-    
     def _cleanup_(self):
         self.before = None        # or a regular RPython function
         self.after = None         # or a regular RPython function
diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -28,11 +28,6 @@
     w_call_startup_gateway = space.wrap(gateway.interp2app(call_startup))
     withjit = space.config.objspace.usemodules.pypyjit
 
-    if withjit:
-        from pypy.module.pypyjit.interp_jit import callback_hook
-        from pypy.rlib import objectmodel
-        objectmodel.register_around_callback_hook(callback_hook)
-
     def entry_point(argv):
         if withjit:
             from pypy.jit.backend.hlinfo import highleveljitinfo


More information about the pypy-commit mailing list