[pypy-commit] pypy default: Test and fix for llexternal(macro=True) seen by the JIT.

arigo noreply at buildbot.pypy.org
Fri Jun 27 11:59:03 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r72251:5fe7c3c02218
Date: 2014-06-27 11:58 +0200
http://bitbucket.org/pypy/pypy/changeset/5fe7c3c02218/

Log:	Test and fix for llexternal(macro=True) seen by the JIT.

diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py b/rpython/jit/backend/llsupport/test/ztranslation_test.py
--- a/rpython/jit/backend/llsupport/test/ztranslation_test.py
+++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py
@@ -10,6 +10,9 @@
 from rpython.jit.backend.test.support import CCompiledMixin
 from rpython.jit.codewriter.policy import StopAtXPolicy
 from rpython.config.config import ConfigError
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.lltypesystem import lltype, rffi
+
 
 class TranslationTest(CCompiledMixin):
     CPUClass = getcpuclass()
@@ -25,6 +28,7 @@
         # - floats neg and abs
         # - threadlocalref_get
         # - get_errno, set_errno
+        # - llexternal with macro=True
 
         class Frame(object):
             _virtualizable_ = ['i']
@@ -36,9 +40,15 @@
             pass
         t = ThreadLocalReference(Foo)
 
-        @dont_look_inside
-        def myabs(x):
-            return abs(x)
+        eci = ExternalCompilationInfo(post_include_bits=['''
+#define pypy_my_fabs(x)  fabs(x)
+'''])
+        myabs1 = rffi.llexternal('pypy_my_fabs', [lltype.Float],
+                                 lltype.Float, macro=True, releasegil=False,
+                                 compilation_info=eci)
+        myabs2 = rffi.llexternal('pypy_my_fabs', [lltype.Float],
+                                 lltype.Float, macro=True, releasegil=True,
+                                 compilation_info=eci)
 
         jitdriver = JitDriver(greens = [],
                               reds = ['total', 'frame', 'j'],
@@ -61,7 +71,7 @@
                 frame.i -= 1
                 j *= -0.712
                 if j + (-j):    raise ValueError
-                k = myabs(j)
+                k = myabs1(myabs2(j))
                 if k - abs(j):  raise ValueError
                 if k - abs(-j): raise ValueError
                 if t.get().nine != 9: raise ValueError
@@ -69,7 +79,6 @@
                 if rposix.get_errno() != total: raise ValueError
             return chr(total % 253)
         #
-        from rpython.rtyper.lltypesystem import lltype, rffi
         from rpython.rlib.libffi import types, CDLL, ArgChain
         from rpython.rlib.test.test_clibffi import get_libm_name
         libm_name = get_libm_name(sys.platform)
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -95,6 +95,8 @@
                 name, macro, ext_type, compilation_info)
         else:
             _callable = ll2ctypes.LL2CtypesCallable(ext_type, calling_conv)
+    else:
+        assert macro is None, "'macro' is useless if you specify '_callable'"
     if elidable_function:
         _callable._elidable_function_ = True
     kwds = {}
@@ -172,7 +174,13 @@
         call_external_function._dont_inline_ = True
         call_external_function._annspecialcase_ = 'specialize:ll'
         call_external_function._gctransformer_hint_close_stack_ = True
-        call_external_function._call_aroundstate_target_ = funcptr
+        #
+        # '_call_aroundstate_target_' is used by the JIT to generate a
+        # CALL_RELEASE_GIL directly to 'funcptr'.  This doesn't work if
+        # 'funcptr' might be a C macro, though.
+        if macro is None:
+            call_external_function._call_aroundstate_target_ = funcptr
+        #
         call_external_function = func_with_new_name(call_external_function,
                                                     'ccall_' + name)
         # don't inline, as a hack to guarantee that no GC pointer is alive
@@ -180,7 +188,16 @@
     else:
         # if we don't have to invoke the aroundstate, we can just call
         # the low-level function pointer carelessly
-        call_external_function = funcptr
+        if macro is None:
+            call_external_function = funcptr
+        else:
+            # ...well, unless it's a macro, in which case we still have
+            # to hide it from the JIT...
+            @jit.dont_look_inside
+            def call_external_function(*args):
+                return funcptr(*args)
+            call_external_function = func_with_new_name(call_external_function,
+                                                        'ccall_' + name)
 
     unrolling_arg_tps = unrolling_iterable(enumerate(args))
     def wrapper(*args):


More information about the pypy-commit mailing list