Commits

Antonio Cuni committed 90482eb

a branch where to fix this failing test about call_release_gil, which is due to the fact that the op is generated inside pyjitpl and thus its resultbox is not included in the guard_not_forced failargs

Comments (0)

Files changed (3)

pypy/jit/backend/llgraph/runner.py

             # manipulation here (as a hack, instead of really doing
             # the aroundstate manipulation ourselves)
             return self.execute_call_may_force(descr, func, *args)
+        guard_op = self.lltrace.operations[self.current_index + 1]
+        assert guard_op.getopnum() == rop.GUARD_NOT_FORCED
+        self.force_guard_op = guard_op
         call_args = support.cast_call_args_in_order(descr.ARGS, args)
-        FUNC = lltype.FuncType(descr.ARGS, descr.RESULT)
-        func_to_call = rffi.cast(lltype.Ptr(FUNC), func)
-        result = func_to_call(*call_args)
+        #
+        func_adr = llmemory.cast_int_to_adr(func)
+        if hasattr(func_adr.ptr._obj, '_callable'):
+            # this is needed e.g. by test_fficall.test_guard_not_forced_fails,
+            # because to actually force the virtualref we need to llinterp the
+            # graph, not to directly execute the python function
+            result = self.cpu.maybe_on_top_of_llinterp(func, call_args, descr.RESULT)
+        else:
+            FUNC = lltype.FuncType(descr.ARGS, descr.RESULT)
+            func_to_call = rffi.cast(lltype.Ptr(FUNC), func)
+            result = func_to_call(*call_args)
+        del self.force_guard_op
         return support.cast_result(descr.RESULT, result)
 
     def execute_call_assembler(self, descr, *args):

pypy/jit/metainterp/history.py

 
     def show(self, errmsg=None):
         "NOT_RPYTHON"
-        from pypy.jit.metainterp.graphpage import display_loops
-        display_loops([self], errmsg)
+        from pypy.jit.metainterp.graphpage import display_procedures
+        display_procedures([self], errmsg)
 
     def check_consistency(self):     # for testing
         "NOT_RPYTHON"

pypy/jit/metainterp/test/test_fficall.py

 import py
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib import jit
                   rffi.cast(rffi.SIGNEDCHAR, -42))
 
 
+    def test_guard_not_forced_fails(self):
+        FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
+
+        cif_description = get_description([types.slong], types.slong)
+        cif_description.exchange_args[0] = 16
+        cif_description.exchange_result = 32
+
+        ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed))
+
+        @jit.dont_look_inside
+        def fn(n):
+            if n >= 50:
+                exctx.m = exctx.topframeref().n # forces the frame
+            return n*2
+
+        @jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
+        def fake_call(cif_description, func_addr, exchange_buffer):
+            # read the args from the buffer
+            data_in = rffi.ptradd(exchange_buffer, 16)
+            n = rffi.cast(ARRAY, data_in)[0]
+            #
+            # logic of the function
+            func_ptr = rffi.cast(lltype.Ptr(FUNC), func_addr)
+            n = func_ptr(n)
+            #
+            # write the result to the buffer
+            data_out = rffi.ptradd(exchange_buffer, 32)
+            rffi.cast(ARRAY, data_out)[0] = n
+
+        def do_call(n):
+            func_ptr = llhelper(lltype.Ptr(FUNC), fn)
+            #func_addr = rffi.cast(rffi.VOIDP, func_ptr)
+            exbuf = lltype.malloc(rffi.CCHARP.TO, 48, flavor='raw', zero=True)
+            data_in = rffi.ptradd(exbuf, 16)
+            rffi.cast(ARRAY, data_in)[0] = n
+            fake_call(cif_description, func_ptr, exbuf)
+            data_out = rffi.ptradd(exbuf, 32)
+            res = rffi.cast(ARRAY, data_out)[0]
+            lltype.free(exbuf, flavor='raw')
+            return res
+
+        #
+        #
+        class XY:
+            pass
+        class ExCtx:
+            pass
+        exctx = ExCtx()
+        myjitdriver = jit.JitDriver(greens = [], reds = ['n'])
+        def f():
+            n = 0
+            while n < 100:
+                myjitdriver.jit_merge_point(n=n)
+                xy = XY()
+                xy.n = n
+                exctx.topframeref = vref = jit.virtual_ref(xy)
+                res = do_call(n) # this is equivalent of a cffi call which
+                                 # sometimes forces a frame
+                assert res == n*2
+                jit.virtual_ref_finish(vref, xy)
+                exctx.topframeref = jit.vref_None
+                n += 1
+            return n
+
+        assert f() == 100
+        res = self.meta_interp(f, [])
+        assert res == 100
+        
+
 class TestFfiCall(FfiCallTests, LLJitMixin):
     pass