Author: Carl Friedrich Bolz-Tereick <cfb...@gmx.de> Branch: py3.6 Changeset: r98685:3aabca3d88f7 Date: 2020-02-08 11:39 +0100 http://bitbucket.org/pypy/pypy/changeset/3aabca3d88f7/
Log: merge default diff --git a/extra_tests/cffi_tests/cffi0/test_function.py b/extra_tests/cffi_tests/cffi0/test_function.py --- a/extra_tests/cffi_tests/cffi0/test_function.py +++ b/extra_tests/cffi_tests/cffi0/test_function.py @@ -521,3 +521,16 @@ assert str(e.value).startswith("library '") assert str(e.value).endswith("' has already been closed") ffi.dlclose(lib) # does not raise + + def test_passing_large_list(self): + if self.Backend is CTypesBackend: + py.test.skip("the ctypes backend doesn't support this") + ffi = FFI(backend=self.Backend()) + ffi.cdef(""" + void getenv(char *); + """) + needs_dlopen_none() + m = ffi.dlopen(None) + arg = [b"F", b"O", b"O"] + [b"\x00"] * 20000000 + x = m.getenv(arg) + assert x is None diff --git a/extra_tests/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py --- a/extra_tests/cffi_tests/cffi0/test_verify.py +++ b/extra_tests/cffi_tests/cffi0/test_verify.py @@ -2551,3 +2551,13 @@ """.replace('?', str(a))) # the verify() crashes if the values in the enum are different from # the values we computed ourselves from the cdef() + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = ffi.verify(""" + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py --- a/extra_tests/cffi_tests/cffi1/test_recompiler.py +++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py @@ -2446,3 +2446,13 @@ }; """) py.test.raises(RuntimeError, ffi.new, "struct BinaryTree *") + +def test_passing_large_list(): + ffi = FFI() + ffi.cdef("""void passing_large_list(long[]);""") + lib = verify(ffi, "test_passing_large_list", """ + static void passing_large_list(long a[]) { } + """) + arg = list(range(20000000)) + lib.passing_large_list(arg) + # assert did not segfault diff --git a/extra_tests/cffi_tests/support.py b/extra_tests/cffi_tests/support.py --- a/extra_tests/cffi_tests/support.py +++ b/extra_tests/cffi_tests/support.py @@ -104,6 +104,7 @@ [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): # assume a standard clang or gcc extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion', + '-Wno-unused-parameter', '-Wno-unreachable-code'] # special things for clang extra_compile_args.append('-Qunused-arguments') diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.13.2 +Version: 1.14.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -5,8 +5,8 @@ from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError -__version__ = "1.13.2" -__version_info__ = (1, 13, 2) +__version__ = "1.14.0" +__version_info__ = (1, 14, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -269,6 +269,54 @@ return _cffi_from_c_wchar3216_t((int)x); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} /********** end CPython-specific section **********/ #else diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -224,7 +224,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.13.2" + "\ncompiled with cffi version: 1.14.0" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -560,23 +560,24 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = (%s)alloca((size_t)datasize);' % ( + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + '(%s)alloca((size_t)datasize) : NULL;' % ( tovar, tp.get_c_name(''))) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -699,9 +700,10 @@ prnt(' %s;' % arg) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): @@ -709,6 +711,7 @@ context = 'result of %s' % name result_decl = ' %s;' % tp.result.get_c_name(' result', context) prnt(result_decl) + prnt(' PyObject *pyresult;') else: result_decl = None result_code = '' @@ -742,9 +745,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py --- a/lib_pypy/cffi/vengine_cpy.py +++ b/lib_pypy/cffi/vengine_cpy.py @@ -275,22 +275,23 @@ tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _extra_local_variables(self, tp, localvars): + def _extra_local_variables(self, tp, localvars, freelines): if isinstance(tp, model.PointerType): localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( self._gettypenum(tp), fromvar, tovar)) self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + 'alloca((size_t)datasize) : NULL;' % (tovar,)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') self._prnt(' %s;' % errcode) self._prnt(' }') @@ -369,15 +370,17 @@ prnt(' %s;' % type.get_c_name(' x%d' % i, context)) # localvars = set() + freelines = set() for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): prnt(' %s;' % (decl,)) # if not isinstance(tp.result, model.VoidType): result_code = 'result = ' context = 'result of %s' % name prnt(' %s;' % tp.result.get_c_name(' result', context)) + prnt(' PyObject *pyresult;') else: result_code = '' # @@ -409,9 +412,14 @@ if numargs == 0: prnt(' (void)noarg; /* unused */') if result_code: - prnt(' return %s;' % + prnt(' pyresult = %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') else: + for freeline in freelines: + prnt(' ' + freeline) prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') prnt('}') @@ -981,6 +989,59 @@ return PyBool_FromLong(was_alive); } +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + static int _cffi_init(void) { PyObject *module, *c_api_object = NULL; diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst --- a/pypy/doc/faq.rst +++ b/pypy/doc/faq.rst @@ -465,14 +465,30 @@ the GC and possibly the JIT. -Why doesn't PyPy move to GitHub, Gitlab, ...? ----------------------------------------------- +.. _git: +.. _github: -We've been quite happy with bitbucket.org. Moving version control systems and -hosting is a lot of hard work: On the one hand, PyPy's mercurial history is -long and gnarly. On the other hand, all our infrastructure (buildbots, -benchmarking, etc) would have to be adapted. So unless somebody steps up and -volunteers to do all that work, it will likely not happen. +Why doesn't PyPy use Git and move to GitHub? +--------------------------------------------- + +We discussed it during the switch away from bitbucket. We concluded that (1) +the Git workflow is not as well suited as the Mercurial workflow for our style, +and (2) moving to github "just because everybody else does" is a argument on +thin grounds. + +For (1), there are a few issues, but maybe the most important one is that the +PyPy repository has got thousands of *named* branches. Git has no equivalent +concept. Git has *branches,* of course, which in Mercurial are called +bookmarks. We're not talking about bookmarks. + +The difference between git branches and named branches is not that important in +a repo with 10 branches (no matter how big). But in the case of PyPy, we have +at the moment 1840 branches. Most are closed by now, of course. But we would +really like to retain (both now and in the future) the ability to look at a +commit from the past, and know in which branch it was made. Please make sure +you understand the difference between the Git and the Mercurial branches to +realize that this is not always possible with Git--- we looked hard, and there +is no built-in way to get this workflow. What is needed for Windows 64 support of PyPy? diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -1,1 +1,1 @@ -VERSION = "1.13.2" +VERSION = "1.14.0" diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.13.2", ("This test_c.py file is for testing a version" +assert __version__ == "1.14.0", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -1405,7 +1405,7 @@ def test_unicode_bug_in_listview_utf8(self): l1 = list(u'\u1234\u2345') - assert l1 == [u'\u1234', '\u2345'] + assert l1 == [u'\u1234', u'\u2345'] def test_list_from_set(self): l = ['a'] diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -26,7 +26,7 @@ s2 = unicode_to_decimal_w(space, w_s) assert s2 == "10" - def test_listview_unicode(self): + def test_listview_ascii(self): w_str = self.space.newutf8('abcd', 4) assert self.space.listview_ascii(w_str) == list("abcd") diff --git a/rpython/rlib/rstruct/runpack.py b/rpython/rlib/rstruct/runpack.py --- a/rpython/rlib/rstruct/runpack.py +++ b/rpython/rlib/rstruct/runpack.py @@ -86,12 +86,12 @@ for i in rg: fmtdesc, rep, mask = self.formats[i] miniglobals['unpacker%d' % i] = fmtdesc.unpack - if mask is not None: - perform_lst.append('master_reader.align(%d)' % mask) if not fmtdesc.needcount: perform_lst.append('unpacker%d(reader%d)' % (i, i)) else: perform_lst.append('unpacker%d(reader%d, %d)' % (i, i, rep)) + if mask is not None: + perform_lst.append('master_reader.align(%d)' % mask) miniglobals['reader_cls%d' % i] = reader_for_pos(i) readers = ";".join(["reader%d = reader_cls%d(master_reader, bigendian)" % (i, i) for i in rg]) diff --git a/rpython/rlib/rstruct/test/test_runpack.py b/rpython/rlib/rstruct/test/test_runpack.py --- a/rpython/rlib/rstruct/test/test_runpack.py +++ b/rpython/rlib/rstruct/test/test_runpack.py @@ -110,6 +110,15 @@ assert unpack(">q", '\xbeMLKJIHH') == -0x41B2B3B4B5B6B7B8 assert unpack(">Q", '\x81BCDEFGH') == 0x8142434445464748 + def test_align(self): + data = struct.pack('BBhi', 1, 2, 3, 4) + def fn(): + a, b, c, d = runpack('BBhi', data) + return a + (b << 4) + (c << 8) + (d << 12) + assert fn() == 0x4321 + assert self.interpret(fn, []) == 0x4321 + + class TestNoFastPath(TestRStruct): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit