Commits

Alexander Hesse committed df8704a Merge

hg merge default

Comments (0)

Files changed (16)

goal/targetpypystandalone.py

     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 rpython.rlib import objectmodel
-        objectmodel.register_around_callback_hook(callback_hook)
-
     def entry_point(argv):
         if withjit:
             from rpython.jit.backend.hlinfo import highleveljitinfo

pypy/module/_cffi_backend/ccallback.py

 
 STDERR = 2
 
+@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

pypy/module/pyexpat/interp_pyexpat.py

 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from pypy.interpreter.error import OperationError
-from rpython.rlib import rgc
+from rpython.rlib import rgc, jit
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
         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)

pypy/module/pypyjit/interp_jit.py

 from rpython.tool.pairtype import extendabletype
 from rpython.rlib.rarithmetic import r_uint, intmask
 from rpython.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside
-from rpython.rlib import jit, objectmodel
+from rpython.rlib import jit
 from rpython.rlib.jit import current_trace_length, unroll_parameters
 import pypy.interpreter.pyopcode   # for side-effects
 from pypy.interpreter.error import OperationError, operationerrfmt
                                     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)
-
-@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

pypy/module/thread/os_thread.py

 Thread support based on OS-level threads.
 """
 
-from rpython.rlib import rthread as thread
+import os
+from pypy.module.thread import ll_thread as thread
 from pypy.module.thread.error import wrap_thread_error
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import unwrap_spec, Arguments
         # run!
         try:
             bootstrapper.run(space, w_callable, args)
-        finally:
-            bootstrapper.nbthreads -= 1
-            # clean up space.threadlocals to remove the ExecutionContext
-            # entry corresponding to the current thread
+            # done
+        except Exception, e:
+            # oups! last-level attempt to recover.
             try:
-                space.threadlocals.leave_thread(space)
-            finally:
-                thread.gc_thread_die()
+                STDERR = 2
+                os.write(STDERR, "Thread exited with ")
+                os.write(STDERR, str(e))
+                os.write(STDERR, "\n")
+            except OSError:
+                pass
+        bootstrapper.nbthreads -= 1
+        thread.gc_thread_die()
     bootstrap = staticmethod(bootstrap)
 
     def acquire(space, w_callable, args):
                 where = 'thread %d started by ' % ident
                 e.write_unraisable(space, where, w_callable)
             e.clear(space)
+        # clean up space.threadlocals to remove the ExecutionContext
+        # entry corresponding to the current thread
+        space.threadlocals.leave_thread(space)
     run = staticmethod(run)
 
 bootstrapper = Bootstrapper()

pypy/module/thread/test/test_gil.py

         def bootstrap():
             try:
                 runme()
-            finally:
-                thread.gc_thread_die()
+            except Exception, e:
+                assert 0
+            thread.gc_thread_die()
         def f():
             state.data = []
             state.datalen1 = 0

rpython/jit/backend/test/test_random.py

 class OperationBuilder(object):
     def __init__(self, cpu, loop, vars):
         self.cpu = cpu
+        if not hasattr(cpu, '_faildescr_keepalive'):
+            cpu._faildescr_keepalive = []
         self.fakemetainterp = FakeMetaInterp()
         self.loop = loop
         self.intvars = [box for box in vars if isinstance(box, BoxInt)]
         if pytest.config.option.output:
             s.close()
 
+    def getfaildescr(self):
+        descr = BasicFailDescr()
+        self.cpu._faildescr_keepalive.append(descr)
+        return descr
+
 class CannotProduceOperation(Exception):
     pass
 
             builder.intvars[:] = original_intvars
         else:
             op = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
-        op.setdescr(BasicFailDescr())
+        op.setdescr(builder.getfaildescr())
         op.setfailargs(fail_subset)
         builder.loop.operations.append(op)
 
     def produce_into(self, builder, r):
         op, passing = self.gen_guard(builder, r)
         builder.loop.operations.append(op)
-        op.setdescr(BasicFailDescr())
+        op.setdescr(builder.getfaildescr())
         op.setfailargs(builder.subset_of_intvars(r))
         if not passing:
             builder.should_fail_by = op
             if v not in used_later:
                 endvars.append(v)
         r.shuffle(endvars)
+        endvars = endvars[:1]
         loop.operations.append(ResOperation(rop.FINISH, endvars, None,
-                                            descr=BasicFailDescr()))
+                                            descr=builder.getfaildescr()))
         if builder.should_fail_by:
             self.should_fail_by = builder.should_fail_by
             self.guard_op = builder.guard_op
             else:
                 op = ResOperation(rop.GUARD_EXCEPTION, [guard_op._exc_box],
                                   BoxPtr())
-            op.setdescr(BasicFailDescr())
+            op.setdescr(self.builder.getfaildescr())
             op.setfailargs([])
             return op
 

rpython/jit/metainterp/test/test_fficall.py

 
 
 class TestFfiCall(FfiCallTests, LLJitMixin):
-    def test_jit_fii_vref(self):
+    def test_jit_ffi_vref(self):
         from rpython.rlib import clibffi
         from rpython.rlib.jit_libffi import jit_ffi_prep_cif, jit_ffi_call
 
             res = exb[3]
             lltype.free(exb, flavor='raw')
             #
-            lltype.free(atypes, flavor='raw')
             return res
             #
         res = self.interp_operations(f, [])
         lltype.free(cd, flavor='raw')
         assert res == math.sin(1.23)
+
+        lltype.free(atypes, flavor='raw')

rpython/jit/metainterp/test/test_warmspot.py

 import py
 from rpython.jit.metainterp.warmspot import get_stats
-from rpython.rlib.jit import JitDriver, set_param, unroll_safe
+from rpython.rlib.jit import JitDriver, set_param, unroll_safe, jit_callback
 from rpython.jit.backend.llgraph import runner
 
 from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
     def test_callback_jit_merge_point(self):
+<<<<<<< local
         from rpython.rlib.objectmodel import register_around_callback_hook
         from rpython.rtyper.lltypesystem import lltype, rffi
         from rpython.translator.tool.cbuild import ExternalCompilationInfo
         def callback_hook(name):
             pass
 
+=======
+        @jit_callback("testing")
+>>>>>>> other
         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():
+            total = 0
+            for i in range(10):
+                total += callback(i, 2)
+            return total
 
-        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)
+        res = self.meta_interp(main, [])
+        assert res == 7 - 3
+        self.check_trace_count(2)
 
 
 class TestLLWarmspot(WarmspotTests, LLJitMixin):

rpython/jit/metainterp/warmspot.py

         jd._jit_merge_point_in = graph
         args = op.args[2:]
         s_binding = self.translator.annotator.binding
-        if op.args[1].value.autoreds:
-            # _portal_args_s is used only by _make_hook_graph, but for now we
-            # declare the various set_jitcell_at, get_printable_location,
-            # etc. as incompatible with autoreds
-            jd._portal_args_s = None
-        else:
-            jd._portal_args_s = [s_binding(v) for v in args]
+        jd._portal_args_s = [s_binding(v) for v in args]
         graph = copygraph(graph)
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
         if func is None:
             return None
         #
-        assert not jitdriver_sd.jitdriver.autoreds, (
-            "reds='auto' is not compatible with JitDriver hooks such as "
-            "{get,set}_jitcell_at, get_printable_location, confirm_enter_jit, etc.")
+        if not onlygreens:
+            assert not jitdriver_sd.jitdriver.autoreds, (
+                "reds='auto' is not compatible with JitDriver hooks such as "
+                "confirm_enter_jit")
         extra_args_s = []
         if s_first_arg is not None:
             extra_args_s.append(s_first_arg)

rpython/rlib/clibffi.py

                                    hints={'callback':True}))
 
 
+@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

rpython/rlib/jit.py

     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
 
             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

rpython/rlib/objectmodel.py

     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 rpython.rtyper.lltypesystem import rffi
-    from rpython.rtyper.annlowlevel import llhelper
-   
-    rffi.aroundstate.callback_hook = hook
-    llhelper(rffi.CallbackHookPtr, hook)
-
 def is_in_callback():
     from rpython.rtyper.lltypesystem import rffi
     return rffi.stackcounter.stacks_counter > 1

rpython/rtyper/lltypesystem/rffi.py

 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rtyper.tool.rfficache import platform, sizeof_c_type
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.annlowlevel import llhelper, llstr
+from rpython.rtyper.annlowlevel import llhelper
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
 from rpython.rlib import jit
     callable_name = getattr(callable, '__name__', '?')
     if callbackholder is not None:
         callbackholder.callbacks[callable] = True
-    callable_name_descr = str(callable).replace('"', '\\"')
     args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))])
     source = py.code.Source(r"""
-        def inner_wrapper(%(args)s):
-            if aroundstate is not None:
-                callback_hook = aroundstate.callback_hook
-                if callback_hook:
-                    callback_hook(llstr("%(callable_name_descr)s"))
-            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:
             # 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" %%
     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
 _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

rpython/rtyper/memory/gctransform/framework.py

         assert self.translator.config.translation.thread
         if hasattr(self.root_walker, 'thread_run_ptr'):
             livevars = self.push_roots(hop)
+            assert not livevars, "live GC var around %s!" % (hop.spaceop,)
             hop.genop("direct_call", [self.root_walker.thread_run_ptr])
             self.pop_roots(hop, livevars)
 
         assert self.translator.config.translation.thread
         if hasattr(self.root_walker, 'thread_die_ptr'):
             livevars = self.push_roots(hop)
+            assert not livevars, "live GC var around %s!" % (hop.spaceop,)
             hop.genop("direct_call", [self.root_walker.thread_die_ptr])
             self.pop_roots(hop, livevars)
 

rpython/rtyper/memory/gctransform/shadowstack.py

         self.gcdata.root_stack_top = llmemory.NULL  # to detect missing restore
 
     def forget_current_state(self):
+        ll_assert(self.gcdata.root_stack_base == self.gcdata.root_stack_top,
+                  "forget_current_state: shadowstack not empty!")
         if self.unused_full_stack:
             llmemory.raw_free(self.unused_full_stack)
         self.unused_full_stack = self.gcdata.root_stack_base