[pypy-svn] r56235 - pypy/dist/pypy/rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Wed Jul 2 13:00:41 CEST 2008
Author: arigo
Date: Wed Jul 2 13:00:37 2008
New Revision: 56235
Modified:
pypy/dist/pypy/rpython/lltypesystem/rffi.py
Log:
Revert r56233 and r56234, as it's not helping in the
case where one of the incoming arguments is a GC
structure itself (e.g. a string).
Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed Jul 2 13:00:37 2008
@@ -101,62 +101,67 @@
# sandboxsafe is a hint for "too-small-ness" (e.g. math functions).
invoke_around_handlers = not sandboxsafe
- # The actual wrapper is generated code in order to avoid *args. The
- # issue is that if malloc-removal is not performed, we cannot write
- # a call to 'funcptr(*real_args)' because this needs to read values
- # from the GC-managed tuple 'real_args', which we cannot do between
- # before() and after() calls.
- argnames = ', '.join(['a%d' % i for i in range(len(args))])
- realargnames = ', '.join(['r%d' % i for i in range(len(args))])
- decode_lines = [
- 'r%d = _decode_arg(ARGS[%d], a%d, tag_invoke_around_handlers)'
- % (i, i, i) for i in range(len(args))]
- decode_lines = '; '.join(decode_lines)
- free_lines = [
- '_maybe_free_arg(ARGS[%d], a%d, r%d)'
- % (i, i, i) for i in range(len(args))]
- free_lines = '; '.join(free_lines)
- if invoke_around_handlers:
- tag_invoke_around_handlers = _tagged_true
- else:
- tag_invoke_around_handlers = _tagged_false
-
- source = py.code.Source("""
- def wrapper(%(argnames)s):
- %(decode_lines)s
- if invoke_around_handlers:
- before = aroundstate.before
- after = aroundstate.after
- if before: before()
- # NB. it is essential that no exception checking occurs after
- # the call to before(), because we don't have the GIL any more!
- # It is also essential that no GC pointer is alive between now
- # and the end of the function, so that the external function
- # calls below don't need to be guarded by GC shadow stack logic
- # that would crash if not protected by the GIL!
- res = funcptr(%(realargnames)s)
- if invoke_around_handlers:
- if after: after()
- %(free_lines)s
- return _decode_result(RESULT, res)
- """ % locals())
-
- # xxx workaround workaround: to avoid strange annotation issues,
- # make one version of _decode_arg for each wrapper
- my_decode_arg = func_with_new_name(_decode_arg, 'decode_arg')
- my_maybe_free_arg = func_with_new_name(_maybe_free_arg, 'maybe_free_arg')
- miniglobals = {'ARGS': args,
- 'RESULT': result,
- 'invoke_around_handlers': invoke_around_handlers,
- 'tag_invoke_around_handlers': tag_invoke_around_handlers,
- 'aroundstate': aroundstate,
- 'funcptr': funcptr,
- '_decode_arg': my_decode_arg,
- '_maybe_free_arg': my_maybe_free_arg,
- '_decode_result': _decode_result,
- }
- exec source.compile() in miniglobals
- wrapper = miniglobals['wrapper']
+ unrolling_arg_tps = unrolling_iterable(enumerate(args))
+ def wrapper(*args):
+ # XXX the next line is a workaround for the annotation bug
+ # shown in rpython.test.test_llann:test_pbctype. Remove it
+ # when the test is fixed...
+ assert isinstance(lltype.Signed, lltype.Number)
+ real_args = ()
+ to_free = ()
+ for i, TARGET in unrolling_arg_tps:
+ arg = args[i]
+ freeme = None
+ if TARGET == CCHARP:
+ if arg is None:
+ arg = lltype.nullptr(CCHARP.TO) # None => (char*)NULL
+ freeme = arg
+ elif isinstance(arg, str):
+ arg = str2charp(arg)
+ # XXX leaks if a str2charp() fails with MemoryError
+ # and was not the first in this function
+ freeme = arg
+ elif _isfunctype(TARGET) and not _isllptr(arg):
+ # XXX pass additional arguments
+ if invoke_around_handlers:
+ arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg,
+ aroundstate))
+ else:
+ arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg))
+ else:
+ SOURCE = lltype.typeOf(arg)
+ if SOURCE != TARGET:
+ if TARGET is lltype.Float:
+ arg = float(arg)
+ elif ((isinstance(SOURCE, lltype.Number)
+ or SOURCE is lltype.Bool)
+ and (isinstance(TARGET, lltype.Number)
+ or TARGET is lltype.Bool)):
+ arg = cast(TARGET, arg)
+ real_args = real_args + (arg,)
+ to_free = to_free + (freeme,)
+ if invoke_around_handlers:
+ before = aroundstate.before
+ after = aroundstate.after
+ if before: before()
+ # NB. it is essential that no exception checking occurs after
+ # the call to before(), because we don't have the GIL any more!
+ # It is also essential that no GC pointer is alive between now
+ # and the end of the function, so that the external function
+ # calls below don't need to be guarded by GC shadow stack logic
+ # that would crash if not protected by the GIL!
+ res = funcptr(*real_args)
+ if invoke_around_handlers:
+ if after: after()
+ for i, TARGET in unrolling_arg_tps:
+ if to_free[i]:
+ lltype.free(to_free[i], flavor='raw')
+ if rarithmetic.r_int is not r_int:
+ if result is INT:
+ return cast(lltype.Signed, res)
+ elif result is UINT:
+ return cast(lltype.Unsigned, res)
+ return res
wrapper._annspecialcase_ = 'specialize:ll'
if invoke_around_handlers:
# don't inline, as a hack to guarantee that no GC pointer is alive
@@ -169,67 +174,10 @@
return func_with_new_name(wrapper, name)
-_tagged_false = lambda: None
-_tagged_true = lambda: None
-
-def _decode_arg(TARGET, arg, tag_invoke_around_handlers):
- """Decode one of the arguments passed to the external function,
- automatically normalizing to the exact low-level type TARGET.
- """
- # XXX the next line is a workaround for the annotation bug
- # shown in rpython.test.test_llann:test_pbctype. Remove it
- # when the test is fixed...
- assert isinstance(lltype.Signed, lltype.Number)
- if TARGET == CCHARP:
- if arg is None:
- arg = lltype.nullptr(CCHARP.TO) # None => (char*)NULL
- elif isinstance(arg, str):
- arg = str2charp(arg)
- # XXX leaks if a str2charp() fails with MemoryError
- # and was not the first in this function
- elif _isfunctype(TARGET) and not _isllptr(arg):
- # XXX pass additional arguments
- wrapper = _make_wrapper_for(TARGET, arg, tag_invoke_around_handlers)
- arg = llhelper(TARGET, wrapper)
- else:
- SOURCE = lltype.typeOf(arg)
- if SOURCE != TARGET:
- if TARGET is lltype.Float:
- arg = float(arg)
- elif ((isinstance(SOURCE, lltype.Number)
- or SOURCE is lltype.Bool)
- and (isinstance(TARGET, lltype.Number)
- or TARGET is lltype.Bool)):
- arg = cast(TARGET, arg)
- return arg
-_decode_arg._annspecialcase_ = 'specialize:ll'
-_decode_arg._always_inline_ = True
-
-def _maybe_free_arg(TARGET, original_arg, decoded_arg):
- if TARGET == CCHARP:
- if isinstance(original_arg, str):
- lltype.free(decoded_arg, flavor='raw')
-_maybe_free_arg._annspecialcase_ = 'specialize:ll'
-_maybe_free_arg._always_inline_ = True
-
-def _decode_result(RESULT, res):
- """Decode the result returned by the low-level function,
- automatically normalizing it to a common RPython type.
- """
- if rarithmetic.r_int is not r_int:
- if RESULT is INT:
- return cast(lltype.Signed, res)
- elif RESULT is UINT:
- return cast(lltype.Unsigned, res)
- return res
-_decode_result._annspecialcase_ = 'specialize:ll'
-_decode_result._always_inline_ = True
-
-def _make_wrapper_for(TP, callable, tag_invoke_around_handlers):
+def _make_wrapper_for(TP, callable, aroundstate=None):
""" Function creating wrappers for callbacks. Note that this is
cheating as we assume constant callbacks and we just memoize wrappers
"""
- invoke_around_handlers = tag_invoke_around_handlers is _tagged_true
if hasattr(callable, '_errorcode_'):
errorcode = callable._errorcode_
else:
@@ -238,7 +186,7 @@
args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))])
source = py.code.Source(r"""
def wrapper(%s): # no *args - no GIL for mallocing the tuple
- if invoke_around_handlers:
+ if aroundstate is not None:
before = aroundstate.before
after = aroundstate.after
else:
@@ -268,7 +216,6 @@
miniglobals['Exception'] = Exception
miniglobals['os'] = os
miniglobals['we_are_translated'] = we_are_translated
- miniglobals['aroundstate'] = aroundstate
exec source.compile() in miniglobals
return miniglobals['wrapper']
_make_wrapper_for._annspecialcase_ = 'specialize:memo'
More information about the Pypy-commit
mailing list