[pypy-commit] pypy cffi-1.0: @elidable needs a bit of care: it cannot be used on functions that
arigo
noreply at buildbot.pypy.org
Fri May 8 21:24:33 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77234:b67dbf9a0ed8
Date: 2015-05-08 20:24 +0200
http://bitbucket.org/pypy/pypy/changeset/b67dbf9a0ed8/
Log: @elidable needs a bit of care: it cannot be used on functions that
indirectly cause external function calls or GIL releases. I hope
that these tweaks are enough.
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -46,11 +46,24 @@
self.w_FFIError = get_ffi_error(space)
self.included_libs = [] # list of W_LibObject's included here
- @jit.elidable
- def parse_string_to_type(self, string, flags):
- try:
- x = self.types_dict[string]
- except KeyError:
+ @jit.elidable_promote()
+ def get_string_to_type(self, string, consider_fn_as_fnptr):
+ x = self.types_dict[string] # KeyError if not found
+ if isinstance(x, W_CType):
+ return x
+ elif consider_fn_as_fnptr:
+ return realize_c_type.unwrap_fn_as_fnptr(x)
+ else:
+ return realize_c_type.unexpected_fn_type(self, x)
+
+ @jit.dont_look_inside
+ def parse_string_to_type(self, string, consider_fn_as_fnptr):
+ # This cannot be made @elidable because it calls general space
+ # functions (indirectly, e.g. via the new_xxx_type() functions).
+ # The get_string_to_type() function above is elidable, and we
+ # hope that in almost all cases, get_string_to_type() has already
+ # found an answer.
+ if string not in self.types_dict:
info = self.ctxobj.info
index = parse_c_type.parse_c_type(info, string)
if index < 0:
@@ -62,20 +75,19 @@
x = realize_c_type.realize_c_type_or_func(
self, self.ctxobj.info.c_output, index)
self.types_dict[string] = x
-
- if isinstance(x, W_CType):
- return x
- elif flags & CONSIDER_FN_AS_FNPTR:
- return realize_c_type.unwrap_fn_as_fnptr(x)
- else:
- return realize_c_type.unexpected_fn_type(self, x)
+ return self.get_string_to_type(string, consider_fn_as_fnptr)
def ffi_type(self, w_x, accept):
space = self.space
if (accept & ACCEPT_STRING) and space.isinstance_w(w_x, space.w_str):
- self = jit.promote(self)
- return self.parse_string_to_type(space.str_w(w_x),
- accept & CONSIDER_FN_AS_FNPTR)
+ string = space.str_w(w_x)
+ consider_fn_as_fnptr = (accept & CONSIDER_FN_AS_FNPTR) != 0
+ if jit.isconstant(string):
+ try:
+ return self.get_string_to_type(string, consider_fn_as_fnptr)
+ except KeyError:
+ pass
+ return self.parse_string_to_type(string, consider_fn_as_fnptr)
if (accept & ACCEPT_CTYPE) and isinstance(w_x, W_CType):
return w_x
if (accept & ACCEPT_CDATA) and isinstance(w_x, W_CData):
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -40,17 +40,23 @@
@jit.elidable_promote()
def _get_attr_elidable(self, attr):
- try:
- w_result = self.dict_w[attr]
- except KeyError:
- index = parse_c_type.search_in_globals(self.ctx, attr)
- if index < 0:
- for lib1 in self.ffi.included_libs:
+ return self.dict_w[attr] # KeyError if not found
+
+ @jit.dont_look_inside
+ def _build_attr(self, attr):
+ index = parse_c_type.search_in_globals(self.ctx, attr)
+ if index < 0:
+ for lib1 in self.ffi.included_libs:
+ try:
w_result = lib1._get_attr_elidable(attr)
- if w_result is not None:
- return w_result
- return None # no active caching, but still @elidable
-
+ except KeyError:
+ w_result = lib1._build_attr(attr)
+ if w_result is None:
+ continue
+ break # found, break out of this loop
+ else:
+ return None # not found at all
+ else:
space = self.space
g = self.ctx.c_globals[index]
op = getop(g.c_type_op)
@@ -101,17 +107,21 @@
raise oefmt(space.w_NotImplementedError,
"in lib_build_attr: op=%d", op)
- self.dict_w[attr] = w_result
+ assert w_result is not None
+ self.dict_w[attr] = w_result
return w_result
def _get_attr(self, w_attr):
attr = self.space.str_w(w_attr)
- w_value = self._get_attr_elidable(attr)
- if w_value is None:
- raise oefmt(self.space.w_AttributeError,
- "cffi lib '%s' has no function,"
- " global variable or constant named '%s'",
- self.libname, attr)
+ try:
+ w_value = self._get_attr_elidable(attr)
+ except KeyError:
+ w_value = self._build_attr(attr)
+ if w_value is None:
+ raise oefmt(self.space.w_AttributeError,
+ "cffi lib '%s' has no function,"
+ " global variable or constant named '%s'",
+ self.libname, attr)
return w_value
def descr_getattribute(self, w_attr):
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -598,7 +598,8 @@
fargs.append(w_farg)
return _new_function_type(space, fargs, w_fresult, bool(ellipsis))
- at jit.elidable
+# can't use @jit.elidable here, because it might call back to random
+# space functions via force_lazy_struct()
def _new_function_type(space, fargs, w_fresult, ellipsis=False):
from pypy.module._cffi_backend import ctypefunc
#
More information about the pypy-commit
mailing list