[pypy-commit] pypy default: propagate the flags of ffi functions into the calldescr, so that call_release_gil will be able to inspect it and use the proper calling convention
antocuni
noreply at buildbot.pypy.org
Wed Aug 31 15:07:46 CEST 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r46945:f411890255ef
Date: 2011-08-31 15:06 +0200
http://bitbucket.org/pypy/pypy/changeset/f411890255ef/
Log: propagate the flags of ffi functions into the calldescr, so that
call_release_gil will be able to inspect it and use the proper
calling convention
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -25,13 +25,14 @@
class Descr(history.AbstractDescr):
def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
- arg_types=None, count_fields_if_immut=-1):
+ arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
self.ofs = ofs
self.typeinfo = typeinfo
self.extrainfo = extrainfo
self.name = name
self.arg_types = arg_types
self.count_fields_if_immut = count_fields_if_immut
+ self.ffi_flags = ffi_flags
def get_arg_types(self):
return self.arg_types
@@ -67,6 +68,9 @@
def count_fields_if_immutable(self):
return self.count_fields_if_immut
+ def get_ffi_flags(self):
+ return self.ffi_flags
+
def __lt__(self, other):
raise TypeError("cannot use comparison on Descrs")
def __le__(self, other):
@@ -114,14 +118,14 @@
return False
def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
- arg_types=None, count_fields_if_immut=-1):
+ arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
key = (ofs, typeinfo, extrainfo, name, arg_types,
- count_fields_if_immut)
+ count_fields_if_immut, ffi_flags)
try:
return self._descrs[key]
except KeyError:
descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
- count_fields_if_immut)
+ count_fields_if_immut, ffi_flags)
self._descrs[key] = descr
return descr
@@ -326,7 +330,7 @@
return self.getdescr(0, token[0], extrainfo=extrainfo,
arg_types=''.join(arg_types))
- def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo):
+ def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo, ffi_flags):
from pypy.jit.backend.llsupport.ffisupport import get_ffi_type_kind
from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind
arg_types = []
@@ -339,7 +343,8 @@
except UnsupportedKind:
return None
return self.getdescr(0, reskind, extrainfo=extrainfo,
- arg_types=''.join(arg_types))
+ arg_types=''.join(arg_types),
+ ffi_flags=ffi_flags)
def grab_exc_value(self):
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -260,10 +260,12 @@
_clsname = ''
loop_token = None
arg_classes = '' # <-- annotation hack
+ ffi_flags = 0
- def __init__(self, arg_classes, extrainfo=None):
+ def __init__(self, arg_classes, extrainfo=None, ffi_flags=0):
self.arg_classes = arg_classes # string of "r" and "i" (ref/int)
self.extrainfo = extrainfo
+ self.ffi_flags = ffi_flags
def __repr__(self):
res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
@@ -284,6 +286,9 @@
def get_extra_info(self):
return self.extrainfo
+ def get_ffi_flags(self):
+ return self.ffi_flags
+
def get_arg_types(self):
return self.arg_classes
@@ -391,8 +396,8 @@
"""
_clsname = 'DynamicIntCallDescr'
- def __init__(self, arg_classes, result_size, result_sign, extrainfo=None):
- BaseIntCallDescr.__init__(self, arg_classes, extrainfo)
+ def __init__(self, arg_classes, result_size, result_sign, extrainfo=None, ffi_flags=0):
+ BaseIntCallDescr.__init__(self, arg_classes, extrainfo, ffi_flags)
assert isinstance(result_sign, bool)
self._result_size = chr(result_size)
self._result_sign = result_sign
diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py
--- a/pypy/jit/backend/llsupport/ffisupport.py
+++ b/pypy/jit/backend/llsupport/ffisupport.py
@@ -8,7 +8,7 @@
class UnsupportedKind(Exception):
pass
-def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None):
+def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None, ffi_flags=0):
"""Get a call descr: the types of result and args are represented by
rlib.libffi.types.*"""
try:
@@ -20,18 +20,24 @@
if reskind == history.INT:
size = intmask(ffi_result.c_size)
signed = is_ffi_type_signed(ffi_result)
- return DynamicIntCallDescr(arg_classes, size, signed, extrainfo)
+ return DynamicIntCallDescr(arg_classes, size, signed, extrainfo,
+ ffi_flags=ffi_flags)
elif reskind == history.REF:
- return NonGcPtrCallDescr(arg_classes, extrainfo)
+ return NonGcPtrCallDescr(arg_classes, extrainfo,
+ ffi_flags=ffi_flags)
elif reskind == history.FLOAT:
- return FloatCallDescr(arg_classes, extrainfo)
+ return FloatCallDescr(arg_classes, extrainfo,
+ ffi_flags=ffi_flags)
elif reskind == history.VOID:
- return VoidCallDescr(arg_classes, extrainfo)
+ return VoidCallDescr(arg_classes, extrainfo,
+ ffi_flags=ffi_flags)
elif reskind == 'L':
- return LongLongCallDescr(arg_classes, extrainfo)
+ return LongLongCallDescr(arg_classes, extrainfo,
+ ffi_flags=ffi_flags)
elif reskind == 'S':
SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
- return SingleFloatCallDescr(arg_classes, extrainfo)
+ return SingleFloatCallDescr(arg_classes, extrainfo,
+ ffi_flags=ffi_flags)
assert False
def get_ffi_type_kind(cpu, ffi_type):
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -257,10 +257,10 @@
def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
return get_call_descr(self.gc_ll_descr, ARGS, RESULT, extrainfo)
- def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo):
+ def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo, ffi_flags):
from pypy.jit.backend.llsupport import ffisupport
return ffisupport.get_call_descr_dynamic(self, ffi_args, ffi_result,
- extrainfo)
+ extrainfo, ffi_flags)
def get_overflow_error(self):
ovf_vtable = self.cast_adr_to_int(self._ovf_error_vtable)
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -13,17 +13,19 @@
def test_call_descr_dynamic():
args = [types.sint, types.pointer]
- descr = get_call_descr_dynamic(FakeCPU(), args, types.sint)
+ descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, ffi_flags=42)
assert isinstance(descr, DynamicIntCallDescr)
assert descr.arg_classes == 'ii'
+ assert descr.get_ffi_flags() == 42
args = [types.sint, types.double, types.pointer]
descr = get_call_descr_dynamic(FakeCPU(), args, types.void)
assert descr is None # missing floats
descr = get_call_descr_dynamic(FakeCPU(supports_floats=True),
- args, types.void)
+ args, types.void, ffi_flags=43)
assert isinstance(descr, VoidCallDescr)
assert descr.arg_classes == 'ifi'
+ assert descr.get_ffi_flags() == 43
descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8)
assert isinstance(descr, DynamicIntCallDescr)
@@ -39,14 +41,16 @@
descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
assert descr is None # missing longlongs
descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
- [], types.slonglong)
+ [], types.slonglong, ffi_flags=43)
assert isinstance(descr, LongLongCallDescr)
+ assert descr.get_ffi_flags() == 43
else:
assert types.slonglong is types.slong
descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
assert descr is None # missing singlefloats
descr = get_call_descr_dynamic(FakeCPU(supports_singlefloats=True),
- [], types.float)
+ [], types.float, ffi_flags=44)
SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
assert isinstance(descr, SingleFloatCallDescr)
+ assert descr.get_ffi_flags() == 44
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -497,7 +497,8 @@
assert res.value == 2 * num
# then, try it with the dynamic calldescr
dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type,
- EffectInfo.MOST_GENERAL)
+ EffectInfo.MOST_GENERAL,
+ ffi_flags=0)
res = self.execute_operation(rop.CALL,
[funcbox, BoxInt(num), BoxInt(num)],
'int', descr=dyn_calldescr)
@@ -1955,7 +1956,8 @@
func_adr = llmemory.cast_ptr_to_adr(c_tolower.funcsym)
funcbox = ConstInt(heaptracker.adr2int(func_adr))
calldescr = cpu.calldescrof_dynamic([types.uchar], types.sint,
- EffectInfo.MOST_GENERAL)
+ EffectInfo.MOST_GENERAL,
+ ffi_flags=0)
i1 = BoxInt()
i2 = BoxInt()
tok = BoxInt()
@@ -2012,7 +2014,8 @@
calldescr = cpu.calldescrof_dynamic([types.pointer, types_size_t,
types_size_t, types.pointer],
types.void,
- EffectInfo.MOST_GENERAL)
+ EffectInfo.MOST_GENERAL,
+ ffi_flags=0)
i0 = BoxInt()
i1 = BoxInt()
i2 = BoxInt()
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -18,26 +18,27 @@
def __init__(self, funcval, cpu, prepare_op):
self.funcval = funcval
self.opargs = []
- argtypes, restype = self._get_signature(funcval)
+ argtypes, restype, flags = self._get_signature(funcval)
self.descr = cpu.calldescrof_dynamic(argtypes, restype,
- EffectInfo.MOST_GENERAL)
+ EffectInfo.MOST_GENERAL,
+ ffi_flags=flags)
# ^^^ may be None if unsupported
self.prepare_op = prepare_op
self.delayed_ops = []
def _get_signature(self, funcval):
"""
- given the funcval, return a tuple (argtypes, restype), where the
- actuall types are libffi.types.*
+ given the funcval, return a tuple (argtypes, restype, flags), where
+ the actuall types are libffi.types.*
The implementation is tricky because we have three possible cases:
- translated: the easiest case, we can just cast back the pointer to
- the original Func instance and read .argtypes and .restype
+ the original Func instance and read .argtypes, .restype and .flags
- completely untranslated: this is what we get from test_optimizeopt
tests. funcval contains a FakeLLObject whose _fake_class is Func,
- and we can just get .argtypes and .restype
+ and we can just get .argtypes, .restype and .flags
- partially translated: this happens when running metainterp tests:
funcval contains the low-level equivalent of a Func, and thus we
@@ -49,10 +50,10 @@
llfunc = funcval.box.getref_base()
if we_are_translated():
func = cast_base_ptr_to_instance(Func, llfunc)
- return func.argtypes, func.restype
+ return func.argtypes, func.restype, func.flags
elif getattr(llfunc, '_fake_class', None) is Func:
# untranslated
- return llfunc.argtypes, llfunc.restype
+ return llfunc.argtypes, llfunc.restype, llfunc.flags
else:
# partially translated
# llfunc contains an opaque pointer to something like the following:
@@ -63,7 +64,7 @@
# because we don't have the exact TYPE to cast to. Instead, we
# just fish it manually :-(
f = llfunc._obj.container
- return f.inst_argtypes, f.inst_restype
+ return f.inst_argtypes, f.inst_restype, f.inst_flags
class OptFfiCall(Optimization):
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizefficall.py
@@ -14,12 +14,15 @@
can check that the signature of a call is really what you want.
"""
- def __init__(self, arg_types, typeinfo):
+ def __init__(self, arg_types, typeinfo, flags):
self.arg_types = arg_types
self.typeinfo = typeinfo # return type
+ self.flags = flags
def __eq__(self, other):
- return self.arg_types == other.arg_types and self.typeinfo == other.typeinfo
+ return (self.arg_types == other.arg_types and
+ self.typeinfo == other.typeinfo and
+ self.flags == other.get_ffi_flags())
class FakeLLObject(object):
@@ -41,14 +44,17 @@
vable_token_descr = LLtypeMixin.valuedescr
valuedescr = LLtypeMixin.valuedescr
- int_float__int = MyCallDescr('if', 'i')
+ int_float__int_42 = MyCallDescr('if', 'i', 42)
+ int_float__int_43 = MyCallDescr('if', 'i', 43)
funcptr = FakeLLObject()
func = FakeLLObject(_fake_class=Func,
argtypes=[types.sint, types.double],
- restype=types.sint)
+ restype=types.sint,
+ flags=42)
func2 = FakeLLObject(_fake_class=Func,
argtypes=[types.sint, types.double],
- restype=types.sint)
+ restype=types.sint,
+ flags=43)
#
def calldescr(cpu, FUNC, oopspecindex, extraeffect=None):
if extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
@@ -83,7 +89,7 @@
"""
expected = """
[i0, f1]
- i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+ i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
guard_not_forced() []
guard_no_exception() []
jump(i3, f1)
@@ -123,7 +129,7 @@
[i0, f1, p2]
i4 = force_token()
setfield_gc(p2, i4, descr=vable_token_descr)
- i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+ i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
guard_not_forced() [p2]
guard_no_exception() [p2]
jump(i3, f1, p2)
@@ -220,7 +226,7 @@
call(0, ConstPtr(func), descr=libffi_prepare)
#
# this "nested" call is nicely optimized
- i4 = call_release_gil(67890, i0, f1, descr=int_float__int)
+ i4 = call_release_gil(67890, i0, f1, descr=int_float__int_43)
guard_not_forced() []
guard_no_exception() []
#
@@ -265,7 +271,7 @@
expected = """
[i0, f1, p2]
setfield_gc(p2, i0, descr=valuedescr)
- i3 = call_release_gil(12345, i0, f1, descr=int_float__int)
+ i3 = call_release_gil(12345, i0, f1, descr=int_float__int_42)
guard_not_forced() []
guard_no_exception() []
jump(i3, f1, p2)
More information about the pypy-commit
mailing list