Author: Armin Rigo <ar...@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)) -@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 # _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit