Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: cling-support Changeset: r89048:2cf0e94f1f19 Date: 2016-12-12 17:30 -0800 http://bitbucket.org/pypy/pypy/changeset/2cf0e94f1f19/
Log: merge default into cling-support branch and fix dummy_backend diff too long, truncating to 2000 out of 7197 lines diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -12,7 +12,6 @@ import sys import os -import shlex import imp from distutils.errors import DistutilsPlatformError @@ -62,11 +61,31 @@ def _init_posix(): """Initialize the module as appropriate for POSIX systems.""" g = {} + g['CC'] = "gcc -pthread" + g['CXX'] = "g++ -pthread" + g['OPT'] = "-DNDEBUG -O2" + g['CFLAGS'] = "-DNDEBUG -O2" + g['CCSHARED'] = "-fPIC" + g['LDSHARED'] = "gcc -pthread -shared" + g['SO'] = [s[0] for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION][0] + g['AR'] = "ar" + g['ARFLAGS'] = "rc" g['EXE'] = "" - g['SO'] = [s[0] for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION][0] g['LIBDIR'] = os.path.join(sys.prefix, 'lib') - g['CC'] = "gcc -pthread" # -pthread might not be valid on OS/X, check - g['OPT'] = "" + g['VERSION'] = get_python_version() + + if sys.platform[:6] == "darwin": + import platform + if platform.machine() == 'i386': + if platform.architecture()[0] == '32bit': + arch = 'i386' + else: + arch = 'x86_64' + else: + # just a guess + arch = platform.machine() + g['LDSHARED'] += ' -undefined dynamic_lookup' + g['CC'] += ' -arch %s' % (arch,) global _config_vars _config_vars = g @@ -103,6 +122,12 @@ _config_vars['prefix'] = PREFIX _config_vars['exec_prefix'] = EXEC_PREFIX + # OS X platforms require special customization to handle + # multi-architecture, multi-os-version installers + if sys.platform == 'darwin': + import _osx_support + _osx_support.customize_config_vars(_config_vars) + if args: vals = [] for name in args: @@ -118,30 +143,80 @@ """ return get_config_vars().get(name) + def customize_compiler(compiler): - """Dummy method to let some easy_install packages that have - optional C speedup components. + """Do any platform-specific customization of a CCompiler instance. + + Mainly needed on Unix, so we can plug in the information that + varies across Unices and is stored in Python's Makefile (CPython) + or hard-coded in _init_posix() (PyPy). """ - def customize(executable, flags): - command = compiler.executables[executable] + flags - setattr(compiler, executable, command) + if compiler.compiler_type == "unix": + if sys.platform == "darwin": + # Perform first-time customization of compiler-related + # config vars on OS X now that we know we need a compiler. + # This is primarily to support Pythons from binary + # installers. The kind and paths to build tools on + # the user system may vary significantly from the system + # that Python itself was built on. Also the user OS + # version and build tools may not support the same set + # of CPU architectures for universal builds. + global _config_vars + # Use get_config_var() to ensure _config_vars is initialized. + if not get_config_var('CUSTOMIZED_OSX_COMPILER'): + import _osx_support + _osx_support.customize_compiler(_config_vars) + _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' - if compiler.compiler_type == "unix": - # compiler_so can be c++ which has no -Wimplicit - #compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit']) - compiler.compiler_so.extend(['-O2', '-fPIC']) - compiler.shared_lib_extension = get_config_var('SO') - if "CPPFLAGS" in os.environ: - cppflags = shlex.split(os.environ["CPPFLAGS"]) - for executable in ('compiler', 'compiler_so', 'linker_so'): - customize(executable, cppflags) - if "CFLAGS" in os.environ: - cflags = shlex.split(os.environ["CFLAGS"]) - for executable in ('compiler', 'compiler_so', 'linker_so'): - customize(executable, cflags) - if "LDFLAGS" in os.environ: - ldflags = shlex.split(os.environ["LDFLAGS"]) - customize('linker_so', ldflags) + (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \ + get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', + 'CCSHARED', 'LDSHARED', 'SO', 'AR', + 'ARFLAGS') + + if 'CC' in os.environ: + newcc = os.environ['CC'] + if (sys.platform == 'darwin' + and 'LDSHARED' not in os.environ + and ldshared.startswith(cc)): + # On OS X, if CC is overridden, use that as the default + # command for LDSHARED as well + ldshared = newcc + ldshared[len(cc):] + cc = newcc + if 'CXX' in os.environ: + cxx = os.environ['CXX'] + if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] + if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always + if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + if 'CFLAGS' in os.environ: + cflags = opt + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + if 'AR' in os.environ: + ar = os.environ['AR'] + if 'ARFLAGS' in os.environ: + archiver = ar + ' ' + os.environ['ARFLAGS'] + else: + archiver = ar + ' ' + ar_flags + + cc_cmd = cc + ' ' + cflags + compiler.set_executables( + preprocessor=cpp, + compiler=cc_cmd, + compiler_so=cc_cmd + ' ' + ccshared, + compiler_cxx=cxx, + linker_so=ldshared, + linker_exe=cc, + archiver=archiver) + + compiler.shared_lib_extension = so_ext from sysconfig_cpython import ( diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py --- a/lib_pypy/_pypy_wait.py +++ b/lib_pypy/_pypy_wait.py @@ -1,3 +1,4 @@ +import os from resource import ffi, lib, _make_struct_rusage __all__ = ["wait3", "wait4"] @@ -7,6 +8,9 @@ status = ffi.new("int *") ru = ffi.new("struct rusage *") pid = lib.wait3(status, options, ru) + if pid == -1: + errno = ffi.errno + raise OSError(errno, os.strerror(errno)) rusage = _make_struct_rusage(ru) @@ -16,6 +20,9 @@ status = ffi.new("int *") ru = ffi.new("struct rusage *") pid = lib.wait4(pid, status, options, ru) + if pid == -1: + errno = ffi.errno + raise OSError(errno, os.strerror(errno)) rusage = _make_struct_rusage(ru) diff --git a/lib_pypy/greenlet.egg-info b/lib_pypy/greenlet.egg-info --- a/lib_pypy/greenlet.egg-info +++ b/lib_pypy/greenlet.egg-info @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: greenlet -Version: 0.4.10 +Version: 0.4.11 Summary: Lightweight in-process concurrent programming Home-page: https://github.com/python-greenlet/greenlet Author: Ralf Schmitt (for CPython), PyPy team diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py --- a/lib_pypy/greenlet.py +++ b/lib_pypy/greenlet.py @@ -1,7 +1,7 @@ import sys import _continuation -__version__ = "0.4.10" +__version__ = "0.4.11" # ____________________________________________________________ # Exceptions diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst --- a/pypy/doc/cppyy.rst +++ b/pypy/doc/cppyy.rst @@ -1,31 +1,19 @@ cppyy: C++ bindings for PyPy ============================ -The cppyy module creates, at run-time, Python-side classes and functions for -C++, by querying a C++ reflection system. -The default system used is `Reflex`_, which extracts the needed information -from C++ header files. -Another current backend is based on `CINT`_, and yet another, more important -one for the medium- to long-term will be based on `cling`_. -The latter sits on top of `llvm`_'s `clang`_, and will therefore allow the use -of C++11. -The work on the cling backend has so far been done only for CPython, but -bringing it to PyPy is a lot less work than developing it in the first place. +The cppyy module delivers dynamic Python-C++ bindings. +It is based on `Cling`_ which, through `LLVM`_/`clang`_, provides C++ +reflection as extracted from header files. +The module itself is built into PyPy (an alternative exists for CPython), but +it requires a backend, installable through pip, to interface with Cling. -.. _Reflex: https://root.cern.ch/how/how-use-reflex -.. _CINT: https://root.cern.ch/introduction-cint -.. _cling: https://root.cern.ch/cling -.. _llvm: http://llvm.org/ +.. _Cling: https://root.cern.ch/cling +.. _LLVM: http://llvm.org/ .. _clang: http://clang.llvm.org/ -This document describes the version of cppyy that lives in the main branch of -PyPy. -The development of cppyy happens in the "reflex-support" branch. - Motivation ---------- - To provide bindings to another language in CPython, you program to a generic C-API that exposes many of the interpreter features. With PyPy, however, there is no such generic C-API, because several of the @@ -47,7 +35,7 @@ by the JIT up until the actual point of call into C++. This means for example, that if variables are already unboxed by the JIT, they can be passed through directly to C++. -Second, a backend such as Reflex (and cling far more so) adds dynamic features +Second, a backend such as Cling adds dynamic features to C++, thus greatly reducing impedance mismatches between the two languages. For example, Reflex is dynamic enough to allow writing runtime bindings generation in python (as opposed to RPython) and this is used to create very diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst --- a/pypy/doc/project-ideas.rst +++ b/pypy/doc/project-ideas.rst @@ -71,8 +71,11 @@ Analyzing performance of applications is always tricky. We have various tools, for example a `jitviewer`_ that help us analyze performance. -The jitviewer shows the code generated by the PyPy JIT in a hierarchical way, -as shown by the screenshot below: +The old tool was partly rewritten and combined with vmprof. The service is +hosted at `vmprof.com`_. + +The following shows an old image of the jitviewer. +The code generated by the PyPy JIT in a hierarchical way: - at the bottom level, it shows the Python source code of the compiled loops @@ -84,13 +87,17 @@ .. image:: image/jitviewer.png -The jitviewer is a web application based on flask and jinja2 (and jQuery on -the client): if you have great web developing skills and want to help PyPy, +The jitviewer is a web application based on django and angularjs: +if you have great web developing skills and want to help PyPy, this is an ideal task to get started, because it does not require any deep -knowledge of the internals. +knowledge of the internals. Head over to `vmprof-python`_, `vmprof-server`_ and +`vmprof-integration`_ to find open issues and documentation. -.. _jitviewer: http://bitbucket.org/pypy/jitviewer - +.. _jitviewer: http://vmprof.com +.. _vmprof.com: http://vmprof.com +.. _vmprof-python: https://github.com/vmprof/vmprof-python +.. _vmprof-server: https://github.com/vmprof/vmprof-server +.. _vmprof-integration: https://github.com/vmprof/vmprof-integration Optimized Unicode Representation -------------------------------- diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -5,6 +5,15 @@ .. this is a revision shortly after release-pypy2.7-v5.6 .. startrev: 7e9787939641 + +Since a while now, PyPy preserves the order of dictionaries and sets. +However, the set literal syntax ``{x, y, z}`` would by mistake build a +set with the opposite order: ``set([z, y, x])``. This has been fixed. +Note that CPython is inconsistent too: in 2.7.12, ``{5, 5.0}`` would be +``set([5.0])``, but in 2.7.trunk it is ``set([5])``. PyPy's behavior +changed in exactly the same way because of this fix. + + .. branch: rpython-error-to-systemerror Any uncaught RPython exception (from a PyPy bug) is turned into an @@ -20,3 +29,19 @@ .. branch: clean-exported-state Clean-ups in the jit optimizeopt + +.. branch: conditional_call_value_4 + +Add jit.conditional_call_elidable(), a way to tell the JIT "conditonally +call this function" returning a result. + +.. branch: desc-specialize + +Refactor FunctionDesc.specialize() and related code (RPython annotator). + +.. branch: raw-calloc + +.. branch: issue2446 + +Assign ``tp_doc`` to the new TypeObject's type dictionary ``__doc__`` key +so it will be picked up by app-level objects of that type diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -298,6 +298,12 @@ if config.translation.sandbox: config.objspace.lonepycfiles = False + if config.objspace.usemodules.cpyext: + if config.translation.gc != 'incminimark': + raise Exception("The 'cpyext' module requires the 'incminimark'" + " GC. You need either 'targetpypystandalone.py" + " --withoutmod-cpyext' or '--gc=incminimark'") + config.translating = True import translate diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py --- a/pypy/interpreter/argument.py +++ b/pypy/interpreter/argument.py @@ -111,7 +111,9 @@ self.keywords = self.keywords + keywords self.keywords_w = self.keywords_w + values_w return + is_dict = False if space.isinstance_w(w_starstararg, space.w_dict): + is_dict = True keys_w = space.unpackiterable(w_starstararg) else: try: @@ -125,7 +127,9 @@ keys_w = space.unpackiterable(w_keys) keywords_w = [None] * len(keys_w) keywords = [None] * len(keys_w) - _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords, keywords_w, self.keywords) + _do_combine_starstarargs_wrapped( + space, keys_w, w_starstararg, keywords, keywords_w, self.keywords, + is_dict) self.keyword_names_w = keys_w if self.keywords is None: self.keywords = keywords @@ -355,7 +359,7 @@ key) def _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords, - keywords_w, existingkeywords): + keywords_w, existingkeywords, is_dict): i = 0 for w_key in keys_w: try: @@ -374,7 +378,16 @@ "got multiple values for keyword argument '%s'", key) keywords[i] = key - keywords_w[i] = space.getitem(w_starstararg, w_key) + if is_dict: + # issue 2435: bug-to-bug compatibility with cpython. for a subclass of + # dict, just ignore the __getitem__ and access the underlying dict + # directly + from pypy.objspace.descroperation import dict_getitem + w_descr = dict_getitem(space) + w_value = space.get_and_call_function(w_descr, w_starstararg, w_key) + else: + w_value = space.getitem(w_starstararg, w_key) + keywords_w[i] = w_value i += 1 @jit.look_inside_iff( diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -183,6 +183,14 @@ assert self._finalize_.im_func is not W_Root._finalize_.im_func space.finalizer_queue.register_finalizer(self) + def may_unregister_rpython_finalizer(self, space): + """Optimization hint only: if there is no user-defined __del__() + method, pass the hint ``don't call any finalizer'' to rgc. + """ + if not self.getclass(space).hasuserdel: + from rpython.rlib import rgc + rgc.may_ignore_finalizer(self) + # hooks that the mapdict implementations needs: def _get_mapdict_map(self): return None diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -439,6 +439,7 @@ space.wrap(msg)) return OperationError(exc, w_error) +@specialize.arg(3) def wrap_oserror2(space, e, w_filename=None, exception_name='w_OSError', w_exception_class=None): assert isinstance(e, OSError) @@ -466,8 +467,8 @@ w_error = space.call_function(exc, space.wrap(errno), space.wrap(msg)) return OperationError(exc, w_error) -wrap_oserror2._annspecialcase_ = 'specialize:arg(3)' +@specialize.arg(3) def wrap_oserror(space, e, filename=None, exception_name='w_OSError', w_exception_class=None): if filename is not None: @@ -478,7 +479,6 @@ return wrap_oserror2(space, e, None, exception_name=exception_name, w_exception_class=w_exception_class) -wrap_oserror._annspecialcase_ = 'specialize:arg(3)' def exception_from_saved_errno(space, w_type): from rpython.rlib.rposix import get_saved_errno diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -547,6 +547,8 @@ @jit.dont_look_inside def _run_finalizers(self): + # called by perform() when we have to "perform" this action, + # and also directly at the end of gc.collect). while True: w_obj = self.space.finalizer_queue.next_dead() if w_obj is None: diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py --- a/pypy/interpreter/generator.py +++ b/pypy/interpreter/generator.py @@ -2,7 +2,7 @@ from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.pyopcode import LoopBlock from pypy.interpreter.pycode import CO_YIELD_INSIDE_TRY -from rpython.rlib import jit +from rpython.rlib import jit, rgc class GeneratorIterator(W_Root): @@ -103,11 +103,11 @@ w_result = frame.execute_frame(w_arg, operr) except OperationError: # errors finish a frame - self.frame = None + self.frame_is_finished() raise # if the frame is now marked as finished, it was RETURNed from if frame.frame_finished_execution: - self.frame = None + self.frame_is_finished() raise OperationError(space.w_StopIteration, space.w_None) else: return w_result # YIELDed @@ -209,7 +209,7 @@ finally: frame.f_backref = jit.vref_None self.running = False - self.frame = None + self.frame_is_finished() return unpack_into unpack_into = _create_unpack_into() unpack_into_w = _create_unpack_into() @@ -228,6 +228,10 @@ break block = block.previous + def frame_is_finished(self): + self.frame = None + rgc.may_ignore_finalizer(self) + def get_printable_location_genentry(bytecode): return '%s <generator>' % (bytecode.get_repr(),) diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1295,9 +1295,10 @@ @jit.unroll_safe def BUILD_SET(self, itemcount, next_instr): w_set = self.space.newset() - for i in range(itemcount): - w_item = self.popvalue() + for i in range(itemcount-1, -1, -1): + w_item = self.peekvalue(i) self.space.call_method(w_set, 'add', w_item) + self.popvalues(itemcount) self.pushvalue(w_set) def STORE_MAP(self, oparg, next_instr): diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py --- a/pypy/interpreter/test/test_argument.py +++ b/pypy/interpreter/test/test_argument.py @@ -120,6 +120,12 @@ raise OperationError(AttributeError, name) return method(*args) + def lookup_in_type(self, cls, name): + return getattr(cls, name) + + def get_and_call_function(self, w_descr, w_obj, *args): + return w_descr.__get__(w_obj)(*args) + def type(self, obj): class Type: def getname(self, space): @@ -805,3 +811,19 @@ assert str(e) == "myerror" else: assert False, "Expected TypeError" + + def test_dict_subclass_with_weird_getitem(self): + # issue 2435: bug-to-bug compatibility with cpython. for a subclass of + # dict, just ignore the __getitem__ and behave like ext_do_call in ceval.c + # which just uses the underlying dict + class d(dict): + def __getitem__(self, key): + return key + + for key in ["foo", u"foo"]: + q = d() + q[key] = "bar" + + def test(**kwargs): + return kwargs + assert test(**q) == {"foo": "bar"} diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py --- a/pypy/interpreter/test/test_compiler.py +++ b/pypy/interpreter/test/test_compiler.py @@ -729,6 +729,10 @@ class AppTestCompiler: + def setup_class(cls): + cls.w_host_is_pypy = cls.space.wrap( + '__pypy__' in sys.builtin_module_names) + def test_bom_with_future(self): s = '\xef\xbb\xbffrom __future__ import division\nx = 1/2' ns = {} @@ -771,6 +775,18 @@ assert math.copysign(1., c[0]) == -1.0 assert math.copysign(1., c[1]) == -1.0 + def test_dict_and_set_literal_order(self): + x = 1 + l1 = list({1:'a', 3:'b', 2:'c', 4:'d'}) + l2 = list({1, 3, 2, 4}) + l3 = list({x:'a', 3:'b', 2:'c', 4:'d'}) + l4 = list({x, 3, 2, 4}) + if not self.host_is_pypy: + # the full test relies on the host Python providing ordered dicts + assert set(l1) == set(l2) == set(l3) == set(l4) == {1, 3, 2, 4} + else: + assert l1 == l2 == l3 == l4 == [1, 3, 2, 4] + ##class TestPythonAstCompiler(BaseTestCompiler): ## def setup_method(self, method): diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py --- a/pypy/interpreter/test/test_pyframe.py +++ b/pypy/interpreter/test/test_pyframe.py @@ -580,3 +580,25 @@ pass sys.settrace(None) assert seen == ['call', 'exception', 'return'] + + def test_generator_trace_stopiteration(self): + import sys + def f(): + yield 5 + gen = f() + assert next(gen) == 5 + seen = [] + def trace_func(frame, event, *args): + print('TRACE:', frame, event, args) + seen.append(event) + return trace_func + def g(): + for x in gen: + never_entered + sys.settrace(trace_func) + g() + sys.settrace(None) + print 'seen:', seen + # on Python 3 we get an extra 'exception' when 'for' catches + # StopIteration + assert seen == ['call', 'line', 'call', 'return', 'return'] diff --git a/pypy/interpreter/test/test_special.py b/pypy/interpreter/test/test_special.py --- a/pypy/interpreter/test/test_special.py +++ b/pypy/interpreter/test/test_special.py @@ -4,9 +4,11 @@ def test_Ellipsis(self): assert Ellipsis == Ellipsis assert repr(Ellipsis) == 'Ellipsis' + assert Ellipsis.__class__.__name__ == 'ellipsis' def test_NotImplemented(self): def f(): return NotImplemented assert f() == NotImplemented assert repr(NotImplemented) == 'NotImplemented' + assert NotImplemented.__class__.__name__ == 'NotImplementedType' diff --git a/pypy/interpreter/test/test_unicodehelper.py b/pypy/interpreter/test/test_unicodehelper.py new file mode 100644 --- /dev/null +++ b/pypy/interpreter/test/test_unicodehelper.py @@ -0,0 +1,26 @@ +from pypy.interpreter.unicodehelper import encode_utf8, decode_utf8 + +class FakeSpace: + pass + +def test_encode_utf8(): + space = FakeSpace() + assert encode_utf8(space, u"abc") == "abc" + assert encode_utf8(space, u"\u1234") == "\xe1\x88\xb4" + assert encode_utf8(space, u"\ud800") == "\xed\xa0\x80" + assert encode_utf8(space, u"\udc00") == "\xed\xb0\x80" + # for the following test, go to lengths to avoid CPython's optimizer + # and .pyc file storage, which collapse the two surrogates into one + c = u"\udc00" + assert encode_utf8(space, u"\ud800" + c) == "\xf0\x90\x80\x80" + +def test_decode_utf8(): + space = FakeSpace() + assert decode_utf8(space, "abc") == u"abc" + assert decode_utf8(space, "\xe1\x88\xb4") == u"\u1234" + assert decode_utf8(space, "\xed\xa0\x80") == u"\ud800" + assert decode_utf8(space, "\xed\xb0\x80") == u"\udc00" + got = decode_utf8(space, "\xed\xa0\x80\xed\xb0\x80") + assert map(ord, got) == [0xd800, 0xdc00] + got = decode_utf8(space, "\xf0\x90\x80\x80") + assert map(ord, got) == [0x10000] diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -770,12 +770,12 @@ ) assert not Cell.typedef.acceptable_as_base_class # no __new__ -Ellipsis.typedef = TypeDef("Ellipsis", +Ellipsis.typedef = TypeDef("ellipsis", __repr__ = interp2app(Ellipsis.descr__repr__), ) assert not Ellipsis.typedef.acceptable_as_base_class # no __new__ -NotImplemented.typedef = TypeDef("NotImplemented", +NotImplemented.typedef = TypeDef("NotImplementedType", __repr__ = interp2app(NotImplemented.descr__repr__), ) assert not NotImplemented.typedef.acceptable_as_base_class # no __new__ diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py --- a/pypy/interpreter/unicodehelper.py +++ b/pypy/interpreter/unicodehelper.py @@ -51,6 +51,10 @@ return result def decode_utf8(space, string): + # Surrogates are accepted and not treated specially at all. + # If there happen to be two 3-bytes encoding a pair of surrogates, + # you still get two surrogate unicode characters in the result. + # These are the Python2 rules; Python3 differs. result, consumed = runicode.str_decode_utf_8( string, len(string), "strict", final=True, errorhandler=decode_error_handler(space), @@ -59,8 +63,9 @@ def encode_utf8(space, uni): # Note that this function never raises UnicodeEncodeError, - # since surrogate pairs are allowed. - # This is not the case with Python3. + # since surrogates are allowed, either paired or lone. + # A paired surrogate is considered like the non-BMP character + # it stands for. These are the Python2 rules; Python3 differs. return runicode.unicode_encode_utf_8( uni, len(uni), "strict", errorhandler=raise_unicode_exception_encode, diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -397,7 +397,7 @@ space = self.space if space.is_none(w_destructor): if isinstance(self, W_CDataGCP): - self.w_destructor = None + self.detach_destructor() return space.w_None raise oefmt(space.w_TypeError, "Can remove destructor only on a object " @@ -604,6 +604,10 @@ self.w_destructor = None self.space.call_function(w_destructor, self.w_original_cdata) + def detach_destructor(self): + self.w_destructor = None + self.may_unregister_rpython_finalizer(self.space) + W_CData.typedef = TypeDef( '_cffi_backend.CData', diff --git a/pypy/module/_cffi_backend/cdlopen.py b/pypy/module/_cffi_backend/cdlopen.py --- a/pypy/module/_cffi_backend/cdlopen.py +++ b/pypy/module/_cffi_backend/cdlopen.py @@ -55,6 +55,7 @@ if not libhandle: raise oefmt(self.ffi.w_FFIError, "library '%s' is already closed", self.libname) + self.may_unregister_rpython_finalizer(self.ffi.space) # Clear the dict to force further accesses to do cdlopen_fetch() # again, and fail because the library was closed. Note that the diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py --- a/pypy/module/_cffi_backend/test/test_ffi_obj.py +++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py @@ -401,7 +401,8 @@ retries += 1 assert retries <= 5 import gc; gc.collect() - assert seen == [40, 40, raw1, raw2] + assert (seen == [40, 40, raw1, raw2] or + seen == [40, 40, raw2, raw1]) assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>" assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>" diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py --- a/pypy/module/_collections/interp_deque.py +++ b/pypy/module/_collections/interp_deque.py @@ -1,4 +1,5 @@ import sys +from rpython.rlib.objectmodel import specialize from pypy.interpreter import gateway from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.typedef import TypeDef, make_weakref_descr @@ -6,7 +7,6 @@ from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.error import OperationError, oefmt from rpython.rlib.debug import check_nonneg -from rpython.rlib.objectmodel import specialize # A `dequeobject` is composed of a doubly-linked list of `block` nodes. diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py --- a/pypy/module/_file/interp_file.py +++ b/pypy/module/_file/interp_file.py @@ -172,6 +172,7 @@ self.newlines = self.stream.getnewlines() self.stream = None self.fd = -1 + self.may_unregister_rpython_finalizer(self.space) openstreams = getopenstreams(self.space) try: del openstreams[stream] diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -233,6 +233,7 @@ except SocketError: # cpython doesn't return any errors on close pass + self.may_unregister_rpython_finalizer(space) def connect_w(self, space, w_addr): """connect(address) diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py --- a/pypy/module/_weakref/interp__weakref.py +++ b/pypy/module/_weakref/interp__weakref.py @@ -217,7 +217,7 @@ return self.space.w_None return w_obj - def descr__eq__(self, space, w_ref2): + def compare(self, space, w_ref2, invert): if not isinstance(w_ref2, W_Weakref): return space.w_NotImplemented ref1 = self @@ -225,11 +225,18 @@ w_obj1 = ref1.dereference() w_obj2 = ref2.dereference() if w_obj1 is None or w_obj2 is None: - return space.is_(ref1, ref2) - return space.eq(w_obj1, w_obj2) + w_res = space.is_(ref1, ref2) + else: + w_res = space.eq(w_obj1, w_obj2) + if invert: + w_res = space.not_(w_res) + return w_res + + def descr__eq__(self, space, w_ref2): + return self.compare(space, w_ref2, invert=False) def descr__ne__(self, space, w_ref2): - return space.not_(space.eq(self, w_ref2)) + return self.compare(space, w_ref2, invert=True) def getlifeline(space, w_obj): lifeline = w_obj.getweakref() diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py --- a/pypy/module/_weakref/test/test_weakref.py +++ b/pypy/module/_weakref/test/test_weakref.py @@ -150,6 +150,14 @@ assert not (ref1 == []) assert ref1 != [] + def test_ne(self): + import _weakref + class X(object): + pass + ref1 = _weakref.ref(X()) + assert ref1.__eq__(X()) is NotImplemented + assert ref1.__ne__(X()) is NotImplemented + def test_getweakrefs(self): import _weakref, gc class A(object): diff --git a/pypy/module/cppyy/bench/Makefile b/pypy/module/cppyy/bench/Makefile --- a/pypy/module/cppyy/bench/Makefile +++ b/pypy/module/cppyy/bench/Makefile @@ -26,4 +26,4 @@ bench02Dict_reflex.so: bench02.h bench02.cxx bench02.xml $(genreflex) bench02.h $(genreflexflags) --selection=bench02.xml -I$(ROOTSYS)/include - g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -std=c++14 -lHistPainter `root-config --libs` $(cppflags) $(cppflags2) + g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -std=c++11 -lHistPainter `root-config --libs` $(cppflags) $(cppflags2) diff --git a/pypy/module/cppyy/capi/cling_capi.py b/pypy/module/cppyy/capi/cling_capi.py --- a/pypy/module/cppyy/capi/cling_capi.py +++ b/pypy/module/cppyy/capi/cling_capi.py @@ -63,7 +63,7 @@ includes=["clingcwrapper.h"], library_dirs=rootlibpath, libraries=["Cling"], - compile_extra=["-fno-strict-aliasing", "-std=c++14"], + compile_extra=["-fno-strict-aliasing", "-std=c++11"], use_cpp_linker=True, ) diff --git a/pypy/module/cppyy/src/dummy_backend.cxx b/pypy/module/cppyy/src/dummy_backend.cxx --- a/pypy/module/cppyy/src/dummy_backend.cxx +++ b/pypy/module/cppyy/src/dummy_backend.cxx @@ -76,51 +76,66 @@ static std::map<std::string, long> s_methods; +int Pseudo_kNothing = 6; +int Pseudo_kSomething = 111; +int Pseudo_kLots = 42; + #define PUBLIC_CPPYY_DATA(dmname, dmtype) \ data.push_back(Cppyy_PseudoDatambrInfo("m_"#dmname, #dmtype, \ - offsetof(dummy::cppyy_test_data, m_##dmname), false)); \ + offsetof(dummy::CppyyTestData, m_##dmname), false)); \ + /* <type> get_<type>() */ \ argtypes.clear(); \ methods.push_back(Cppyy_PseudoMethodInfo( \ "get_"#dmname, argtypes, #dmtype)); \ - s_methods["cppyy_test_data::get_"#dmname] = s_method_id++; \ + s_methods["CppyyTestData::get_"#dmname] = s_method_id++; \ + /* <type>& get_<type>_r() */ \ + methods.push_back(Cppyy_PseudoMethodInfo( \ + "get_"#dmname"_r", argtypes, #dmtype"&")); \ + s_methods["CppyyTestData::get_"#dmname"_r"] = s_method_id++; \ + /* const <type>& get_<type>_cr() */ \ + methods.push_back(Cppyy_PseudoMethodInfo( \ + "get_"#dmname"_cr", argtypes, "const "#dmtype"&")); \ + s_methods["CppyyTestData::get_"#dmname"_cr"] = s_method_id++; \ + /* void set_<type>(<type>) */ \ argtypes.push_back(#dmtype); \ methods.push_back(Cppyy_PseudoMethodInfo( \ "set_"#dmname, argtypes, "void")); \ - s_methods["cppyy_test_data::set_"#dmname] = s_method_id++; \ + s_methods["CppyyTestData::set_"#dmname] = s_method_id++; \ argtypes.clear(); \ + /* void set_<type>(const <type>&) */ \ argtypes.push_back("const "#dmtype"&"); \ methods.push_back(Cppyy_PseudoMethodInfo( \ - "set_"#dmname"_c", argtypes, "void")); \ - s_methods["cppyy_test_data::set_"#dmname"_c"] = s_method_id++ + "set_"#dmname"_cr", argtypes, "void")); \ + s_methods["CppyyTestData::set_"#dmname"_cr"] = s_method_id++ #define PUBLIC_CPPYY_DATA2(dmname, dmtype) \ PUBLIC_CPPYY_DATA(dmname, dmtype); \ data.push_back(Cppyy_PseudoDatambrInfo("m_"#dmname"_array", #dmtype"[5]", \ - offsetof(dummy::cppyy_test_data, m_##dmname##_array), false)); \ + offsetof(dummy::CppyyTestData, m_##dmname##_array), false)); \ data.push_back(Cppyy_PseudoDatambrInfo("m_"#dmname"_array2", #dmtype"*", \ - offsetof(dummy::cppyy_test_data, m_##dmname##_array2), false)); \ + offsetof(dummy::CppyyTestData, m_##dmname##_array2), false)); \ argtypes.clear(); \ methods.push_back(Cppyy_PseudoMethodInfo( \ "get_"#dmname"_array", argtypes, #dmtype"*")); \ - s_methods["cppyy_test_data::get_"#dmname"_array"] = s_method_id++; \ + s_methods["CppyyTestData::get_"#dmname"_array"] = s_method_id++; \ methods.push_back(Cppyy_PseudoMethodInfo( \ "get_"#dmname"_array2", argtypes, #dmtype"*")); \ - s_methods["cppyy_test_data::get_"#dmname"_array2"] = s_method_id++ + s_methods["CppyyTestData::get_"#dmname"_array2"] = s_method_id++ #define PUBLIC_CPPYY_DATA3(dmname, dmtype, key) \ PUBLIC_CPPYY_DATA2(dmname, dmtype); \ argtypes.push_back(#dmtype"*"); \ methods.push_back(Cppyy_PseudoMethodInfo( \ "pass_array", argtypes, #dmtype"*")); \ - s_methods["cppyy_test_data::pass_array_"#dmname] = s_method_id++; \ + s_methods["CppyyTestData::pass_array_"#dmname] = s_method_id++; \ argtypes.clear(); argtypes.push_back("void*"); \ methods.push_back(Cppyy_PseudoMethodInfo( \ "pass_void_array_"#key, argtypes, #dmtype"*")); \ - s_methods["cppyy_test_data::pass_void_array_"#key] = s_method_id++ + s_methods["CppyyTestData::pass_void_array_"#key] = s_method_id++ #define PUBLIC_CPPYY_STATIC_DATA(dmname, dmtype) \ data.push_back(Cppyy_PseudoDatambrInfo("s_"#dmname, #dmtype, \ - (ptrdiff_t)&dummy::cppyy_test_data::s_##dmname, true)) + (ptrdiff_t)&dummy::CppyyTestData::s_##dmname, true)) struct Cppyy_InitPseudoReflectionInfo { @@ -284,22 +299,23 @@ //==================================================================== - { // class cppyy_test_data -- - s_handles["cppyy_test_data"] = (cppyy_scope_t)++s_scope_id; + { // class CppyyTestData -- + s_handles["CppyyTestData"] = (cppyy_scope_t)++s_scope_id; std::vector<Cppyy_PseudoMethodInfo> methods; - // cppyy_test_data() + // CppyyTestData() std::vector<std::string> argtypes; - methods.push_back(Cppyy_PseudoMethodInfo("cppyy_test_data", argtypes, "constructor", kConstructor)); - s_methods["cppyy_test_data::cppyy_test_data"] = s_method_id++; + methods.push_back(Cppyy_PseudoMethodInfo("CppyyTestData", argtypes, "constructor", kConstructor)); + s_methods["CppyyTestData::CppyyTestData"] = s_method_id++; methods.push_back(Cppyy_PseudoMethodInfo("destroy_arrays", argtypes, "void")); - s_methods["cppyy_test_data::destroy_arrays"] = s_method_id++; + s_methods["CppyyTestData::destroy_arrays"] = s_method_id++; std::vector<Cppyy_PseudoDatambrInfo> data; PUBLIC_CPPYY_DATA2(bool, bool); PUBLIC_CPPYY_DATA (char, char); + PUBLIC_CPPYY_DATA (schar, signed char); PUBLIC_CPPYY_DATA (uchar, unsigned char); PUBLIC_CPPYY_DATA3(short, short, h); PUBLIC_CPPYY_DATA3(ushort, unsigned short, H); @@ -309,12 +325,16 @@ PUBLIC_CPPYY_DATA3(ulong, unsigned long, L); PUBLIC_CPPYY_DATA (llong, long long); PUBLIC_CPPYY_DATA (ullong, unsigned long long); + PUBLIC_CPPYY_DATA (long64, Long64_t); + PUBLIC_CPPYY_DATA (ulong64, ULong64_t); PUBLIC_CPPYY_DATA3(float, float, f); PUBLIC_CPPYY_DATA3(double, double, d); - PUBLIC_CPPYY_DATA (enum, cppyy_test_data::what); + PUBLIC_CPPYY_DATA (ldouble, long double); + PUBLIC_CPPYY_DATA (enum, CppyyTestData::EWhat); PUBLIC_CPPYY_DATA (voidp, void*); PUBLIC_CPPYY_STATIC_DATA(char, char); + PUBLIC_CPPYY_STATIC_DATA(schar, signed char); PUBLIC_CPPYY_STATIC_DATA(uchar, unsigned char); PUBLIC_CPPYY_STATIC_DATA(short, short); PUBLIC_CPPYY_STATIC_DATA(ushort, unsigned short); @@ -324,14 +344,25 @@ PUBLIC_CPPYY_STATIC_DATA(ulong, unsigned long); PUBLIC_CPPYY_STATIC_DATA(llong, long long); PUBLIC_CPPYY_STATIC_DATA(ullong, unsigned long long); + PUBLIC_CPPYY_STATIC_DATA(long64, Long64_t); + PUBLIC_CPPYY_STATIC_DATA(ulong64, ULong64_t); PUBLIC_CPPYY_STATIC_DATA(float, float); PUBLIC_CPPYY_STATIC_DATA(double, double); - PUBLIC_CPPYY_STATIC_DATA(enum, cppyy_test_data::what); + PUBLIC_CPPYY_STATIC_DATA(ldouble, long double); + PUBLIC_CPPYY_STATIC_DATA(enum, CppyyTestData::EWhat); PUBLIC_CPPYY_STATIC_DATA(voidp, void*); + // pretend enum values + data.push_back(Cppyy_PseudoDatambrInfo( + "kNothing", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kNothing, true)); + data.push_back(Cppyy_PseudoDatambrInfo( + "kSomething", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kSomething, true)); + data.push_back(Cppyy_PseudoDatambrInfo( + "kLots", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kLots, true)); + Cppyy_PseudoClassInfo info(methods, s_method_id - methods.size(), data); s_scopes[(cppyy_scope_t)s_scope_id] = info; - } // -- class cppyy_test_data + } // -- class CppyyTest_data } } _init; @@ -385,78 +416,78 @@ } else if (idx == s_methods["example01::setPayload_payload*"]) { assert(self && nargs == 1); ((dummy::example01*)self)->setPayload((dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::destroy_arrays"]) { + } else if (idx == s_methods["CppyyTestData::destroy_arrays"]) { assert(self && nargs == 0); - ((dummy::cppyy_test_data*)self)->destroy_arrays(); - } else if (idx == s_methods["cppyy_test_data::set_bool"]) { + ((dummy::CppyyTestData*)self)->destroy_arrays(); + } else if (idx == s_methods["CppyyTestData::set_bool"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_bool((bool)((CPPYY_G__value*)args)[0].obj.i); - } else if (idx == s_methods["cppyy_test_data::set_char"]) { + ((dummy::CppyyTestData*)self)->set_bool((bool)((CPPYY_G__value*)args)[0].obj.i); + } else if (idx == s_methods["CppyyTestData::set_char"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_char(((CPPYY_G__value*)args)[0].obj.ch); - } else if (idx == s_methods["cppyy_test_data::set_uchar"]) { + ((dummy::CppyyTestData*)self)->set_char(((CPPYY_G__value*)args)[0].obj.ch); + } else if (idx == s_methods["CppyyTestData::set_uchar"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_uchar(((CPPYY_G__value*)args)[0].obj.uch); - } else if (idx == s_methods["cppyy_test_data::set_short"]) { + ((dummy::CppyyTestData*)self)->set_uchar(((CPPYY_G__value*)args)[0].obj.uch); + } else if (idx == s_methods["CppyyTestData::set_short"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_short(((CPPYY_G__value*)args)[0].obj.sh); - } else if (idx == s_methods["cppyy_test_data::set_short_c"]) { + ((dummy::CppyyTestData*)self)->set_short(((CPPYY_G__value*)args)[0].obj.sh); + } else if (idx == s_methods["CppyyTestData::set_short_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_short_c(*(short*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_ushort"]) { + ((dummy::CppyyTestData*)self)->set_short_cr(*(short*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_ushort"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ushort(((CPPYY_G__value*)args)[0].obj.ush); - } else if (idx == s_methods["cppyy_test_data::set_ushort_c"]) { + ((dummy::CppyyTestData*)self)->set_ushort(((CPPYY_G__value*)args)[0].obj.ush); + } else if (idx == s_methods["CppyyTestData::set_ushort_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ushort_c(*(unsigned short*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_int"]) { + ((dummy::CppyyTestData*)self)->set_ushort_cr(*(unsigned short*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_int"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_int(((CPPYY_G__value*)args)[0].obj.in); - } else if (idx == s_methods["cppyy_test_data::set_int_c"]) { + ((dummy::CppyyTestData*)self)->set_int(((CPPYY_G__value*)args)[0].obj.in); + } else if (idx == s_methods["CppyyTestData::set_int_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_int_c(*(int*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_uint"]) { + ((dummy::CppyyTestData*)self)->set_int_cr(*(int*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_uint"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_uint(((CPPYY_G__value*)args)[0].obj.uin); - } else if (idx == s_methods["cppyy_test_data::set_uint_c"]) { + ((dummy::CppyyTestData*)self)->set_uint(((CPPYY_G__value*)args)[0].obj.uin); + } else if (idx == s_methods["CppyyTestData::set_uint_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_uint_c(*(unsigned int*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_long"]) { + ((dummy::CppyyTestData*)self)->set_uint_cr(*(unsigned int*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_long"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_long(((CPPYY_G__value*)args)[0].obj.i); - } else if (idx == s_methods["cppyy_test_data::set_long_c"]) { + ((dummy::CppyyTestData*)self)->set_long(((CPPYY_G__value*)args)[0].obj.i); + } else if (idx == s_methods["CppyyTestData::set_long_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_long_c(*(long*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_ulong"]) { + ((dummy::CppyyTestData*)self)->set_long_cr(*(long*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_ulong"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ulong(((CPPYY_G__value*)args)[0].obj.ulo); - } else if (idx == s_methods["cppyy_test_data::set_ulong_c"]) { + ((dummy::CppyyTestData*)self)->set_ulong(((CPPYY_G__value*)args)[0].obj.ulo); + } else if (idx == s_methods["CppyyTestData::set_ulong_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ulong_c(*(unsigned long*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_llong"]) { + ((dummy::CppyyTestData*)self)->set_ulong_cr(*(unsigned long*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_llong"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_llong(((CPPYY_G__value*)args)[0].obj.ll); - } else if (idx == s_methods["cppyy_test_data::set_llong_c"]) { + ((dummy::CppyyTestData*)self)->set_llong(((CPPYY_G__value*)args)[0].obj.ll); + } else if (idx == s_methods["CppyyTestData::set_llong_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_llong_c(*(long long*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_ullong"]) { + ((dummy::CppyyTestData*)self)->set_llong_cr(*(long long*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_ullong"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ullong(((CPPYY_G__value*)args)[0].obj.ull); - } else if (idx == s_methods["cppyy_test_data::set_ullong_c"]) { + ((dummy::CppyyTestData*)self)->set_ullong(((CPPYY_G__value*)args)[0].obj.ull); + } else if (idx == s_methods["CppyyTestData::set_ullong_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_ullong_c(*(unsigned long*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_float"]) { + ((dummy::CppyyTestData*)self)->set_ullong_cr(*(unsigned long*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_float"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_float(((CPPYY_G__value*)args)[0].obj.fl); - } else if (idx == s_methods["cppyy_test_data::set_float_c"]) { + ((dummy::CppyyTestData*)self)->set_float(((CPPYY_G__value*)args)[0].obj.fl); + } else if (idx == s_methods["CppyyTestData::set_float_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_float_c(*(float*)&((CPPYY_G__value*)args)[0]); - } else if (idx == s_methods["cppyy_test_data::set_double"]) { + ((dummy::CppyyTestData*)self)->set_float_cr(*(float*)&((CPPYY_G__value*)args)[0]); + } else if (idx == s_methods["CppyyTestData::set_double"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_double(((CPPYY_G__value*)args)[0].obj.d); - } else if (idx == s_methods["cppyy_test_data::set_double_c"]) { + ((dummy::CppyyTestData*)self)->set_double(((CPPYY_G__value*)args)[0].obj.d); + } else if (idx == s_methods["CppyyTestData::set_double_cr"]) { assert(self && nargs == 1); - ((dummy::cppyy_test_data*)self)->set_double_c(*(double*)&((CPPYY_G__value*)args)[0]); + ((dummy::CppyyTestData*)self)->set_double_cr(*(double*)&((CPPYY_G__value*)args)[0]); } else { assert(!"method unknown in cppyy_call_v"); } @@ -465,9 +496,9 @@ unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { unsigned char result = 0; const long idx = (long)method; - if (idx == s_methods["cppyy_test_data::get_bool"]) { + if (idx == s_methods["CppyyTestData::get_bool"]) { assert(self && nargs == 0); - result = (unsigned char)((dummy::cppyy_test_data*)self)->get_bool(); + result = (unsigned char)((dummy::CppyyTestData*)self)->get_bool(); } else { assert(!"method unknown in cppyy_call_b"); } @@ -477,12 +508,12 @@ char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { char result = 0; const long idx = (long)method; - if (idx == s_methods["cppyy_test_data::get_char"]) { + if (idx == s_methods["CppyyTestData::get_char"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_char(); - } else if (idx == s_methods["cppyy_test_data::get_uchar"]) { + result = ((dummy::CppyyTestData*)self)->get_char(); + } else if (idx == s_methods["CppyyTestData::get_uchar"]) { assert(self && nargs == 0); - result = (char)((dummy::cppyy_test_data*)self)->get_uchar(); + result = (char)((dummy::CppyyTestData*)self)->get_uchar(); } else { assert(!"method unknown in cppyy_call_c"); } @@ -492,12 +523,12 @@ short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { short result = 0; const long idx = (long)method; - if (idx == s_methods["cppyy_test_data::get_short"]) { + if (idx == s_methods["CppyyTestData::get_short"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_short(); - } else if (idx == s_methods["cppyy_test_data::get_ushort"]) { + result = ((dummy::CppyyTestData*)self)->get_short(); + } else if (idx == s_methods["CppyyTestData::get_ushort"]) { assert(self && nargs == 0); - result = (short)((dummy::cppyy_test_data*)self)->get_ushort(); + result = (short)((dummy::CppyyTestData*)self)->get_ushort(); } else { assert(!"method unknown in cppyy_call_h"); } @@ -527,9 +558,9 @@ assert(self && nargs == 1); result = ((dummy::example01*)self)->addDataToAtoi( (const char*)(*(long*)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::get_int"]) { + } else if (idx == s_methods["CppyyTestData::get_int"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_int(); + result = ((dummy::CppyyTestData*)self)->get_int(); } else { assert(!"method unknown in cppyy_call_i"); } @@ -556,120 +587,120 @@ assert(self && nargs == 1); result = (long)((dummy::example01*)self)->cyclePayload( (dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::get_uint"]) { + } else if (idx == s_methods["CppyyTestData::get_uint"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_uint(); - } else if (idx == s_methods["cppyy_test_data::get_long"]) { + result = (long)((dummy::CppyyTestData*)self)->get_uint(); + } else if (idx == s_methods["CppyyTestData::get_long"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_long(); - } else if (idx == s_methods["cppyy_test_data::get_ulong"]) { + result = ((dummy::CppyyTestData*)self)->get_long(); + } else if (idx == s_methods["CppyyTestData::get_ulong"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_ulong(); - } else if (idx == s_methods["cppyy_test_data::get_bool_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_ulong(); + } else if (idx == s_methods["CppyyTestData::get_bool_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_bool_array(); - } else if (idx == s_methods["cppyy_test_data::get_bool_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_bool_array(); + } else if (idx == s_methods["CppyyTestData::get_bool_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_bool_array2(); - } else if (idx == s_methods["cppyy_test_data::get_short_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_bool_array2(); + } else if (idx == s_methods["CppyyTestData::get_short_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_short_array(); - } else if (idx == s_methods["cppyy_test_data::get_short_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_short_array(); + } else if (idx == s_methods["CppyyTestData::get_short_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_short_array2(); - } else if (idx == s_methods["cppyy_test_data::get_ushort_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_short_array2(); + } else if (idx == s_methods["CppyyTestData::get_ushort_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_ushort_array(); - } else if (idx == s_methods["cppyy_test_data::get_ushort_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_ushort_array(); + } else if (idx == s_methods["CppyyTestData::get_ushort_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_ushort_array2(); - } else if (idx == s_methods["cppyy_test_data::get_int_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_ushort_array2(); + } else if (idx == s_methods["CppyyTestData::get_int_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_int_array(); - } else if (idx == s_methods["cppyy_test_data::get_int_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_int_array(); + } else if (idx == s_methods["CppyyTestData::get_int_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_int_array2(); - } else if (idx == s_methods["cppyy_test_data::get_uint_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_int_array2(); + } else if (idx == s_methods["CppyyTestData::get_uint_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_uint_array(); - } else if (idx == s_methods["cppyy_test_data::get_uint_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_uint_array(); + } else if (idx == s_methods["CppyyTestData::get_uint_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_uint_array2(); - } else if (idx == s_methods["cppyy_test_data::get_long_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_uint_array2(); + } else if (idx == s_methods["CppyyTestData::get_long_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_long_array(); - } else if (idx == s_methods["cppyy_test_data::get_long_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_long_array(); + } else if (idx == s_methods["CppyyTestData::get_long_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_long_array2(); - } else if (idx == s_methods["cppyy_test_data::get_ulong_array"]) { + result = (long)((dummy::CppyyTestData*)self)->get_long_array2(); + } else if (idx == s_methods["CppyyTestData::get_ulong_array"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_ulong_array(); - } else if (idx == s_methods["cppyy_test_data::get_ulong_array2"]) { + result = (long)((dummy::CppyyTestData*)self)->get_ulong_array(); + } else if (idx == s_methods["CppyyTestData::get_ulong_array2"]) { assert(self && nargs == 0); - result = (long)((dummy::cppyy_test_data*)self)->get_ulong_array2(); - } else if (idx == s_methods["cppyy_test_data::pass_array_short"]) { + result = (long)((dummy::CppyyTestData*)self)->get_ulong_array2(); + } else if (idx == s_methods["CppyyTestData::pass_array_short"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(short**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_h"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_h"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_h( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_h( (*(short**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_ushort"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_ushort"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(unsigned short**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_H"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_H"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_H( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_H( (*(unsigned short**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_int"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_int"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(int**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_i"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_i"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_i( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_i( (*(int**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_uint"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_uint"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(unsigned int**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_I"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_I"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_I( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_I( (*(unsigned int**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_long"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_long"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(long**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_l"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_l"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_l( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_l( (*(long**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_ulong"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_ulong"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(unsigned long**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_L"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_L"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_L( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_L( (*(unsigned long**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_float"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_float"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(float**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_f"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_f"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_f( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_f( (*(float**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_array_double"]) { + } else if (idx == s_methods["CppyyTestData::pass_array_double"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_array( + result = (long)((dummy::CppyyTestData*)self)->pass_array( (*(double**)&((CPPYY_G__value*)args)[0])); - } else if (idx == s_methods["cppyy_test_data::pass_void_array_d"]) { + } else if (idx == s_methods["CppyyTestData::pass_void_array_d"]) { assert(self && nargs == 1); - result = (long)((dummy::cppyy_test_data*)self)->pass_void_array_d( + result = (long)((dummy::CppyyTestData*)self)->pass_void_array_d( (*(double**)&((CPPYY_G__value*)args)[0])); } else { assert(!"method unknown in cppyy_call_l"); @@ -680,12 +711,12 @@ long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { long long result = 0; const long idx = (long)method; - if (idx == s_methods["cppyy_test_data::get_llong"]) { + if (idx == s_methods["CppyyTestData::get_llong"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_llong(); - } else if (idx == s_methods["cppyy_test_data::get_ullong"]) { + result = ((dummy::CppyyTestData*)self)->get_llong(); + } else if (idx == s_methods["CppyyTestData::get_ullong"]) { assert(self && nargs == 0); - result = (long long)((dummy::cppyy_test_data*)self)->get_ullong(); + result = (long long)((dummy::CppyyTestData*)self)->get_ullong(); } else { assert(!"method unknown in cppyy_call_ll"); } @@ -695,9 +726,9 @@ float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { float result = 0; const long idx = (long)method; - if (idx == s_methods["cppyy_test_data::get_float"]) { + if (idx == s_methods["CppyyTestData::get_float"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_float(); + result = ((dummy::CppyyTestData*)self)->get_float(); } else { assert(!"method unknown in cppyy_call_f"); } @@ -716,15 +747,48 @@ } else if (idx == s_methods["payload::getData"]) { assert(self && nargs == 0); result = ((dummy::payload*)self)->getData(); - } else if (idx == s_methods["cppyy_test_data::get_double"]) { + } else if (idx == s_methods["CppyyTestData::get_double"]) { assert(self && nargs == 0); - result = ((dummy::cppyy_test_data*)self)->get_double(); + result = ((dummy::CppyyTestData*)self)->get_double(); } else { assert(!"method unknown in cppyy_call_d"); } return result; } +#define DISPATCH_CALL_R_GET(tpname) \ + else if (idx == s_methods["CppyyTestData::get_"#tpname"_r"]) { \ + assert(self && nargs == 0); \ + result = (void*)&((dummy::CppyyTestData*)self)->get_##tpname##_r(); \ + } else if (idx == s_methods["CppyyTestData::get_"#tpname"_cr"]) { \ + assert(self && nargs == 0); \ + result = (void*)&((dummy::CppyyTestData*)self)->get_##tpname##_cr(); \ + } + +void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { + void* result = nullptr; + const long idx = (long)method; + if (0) {} + DISPATCH_CALL_R_GET(bool) + DISPATCH_CALL_R_GET(short) + DISPATCH_CALL_R_GET(ushort) + DISPATCH_CALL_R_GET(int) + DISPATCH_CALL_R_GET(uint) + DISPATCH_CALL_R_GET(long) + DISPATCH_CALL_R_GET(ulong) + DISPATCH_CALL_R_GET(llong) + DISPATCH_CALL_R_GET(ullong) + DISPATCH_CALL_R_GET(long64) + DISPATCH_CALL_R_GET(ulong64) + DISPATCH_CALL_R_GET(float) + DISPATCH_CALL_R_GET(double) + DISPATCH_CALL_R_GET(ldouble) + else { + assert(!"method unknown in cppyy_call_r"); + } + return result; +} + char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, size_t* /* length */) { char* result = 0; const long idx = (long)method; @@ -750,9 +814,9 @@ assert(nargs == 0 || nargs == 1); if (nargs == 0) result = new dummy::payload; else if (nargs == 1) result = new dummy::payload(((CPPYY_G__value*)args)[0].obj.d); - } else if (idx == s_methods["cppyy_test_data::cppyy_test_data"]) { + } else if (idx == s_methods["CppyyTestData::CppyyTestData"]) { assert(nargs == 0); - result = new dummy::cppyy_test_data; + result = new dummy::CppyyTestData; } else { assert(!"method unknown in cppyy_constructor"); } @@ -792,11 +856,17 @@ return 0; } +int cppyy_is_template(const char* /* template_name */) { + return 0; +} + int cppyy_is_abstract(cppyy_type_t /* type) */) { return 0; } -int cppyy_is_enum(const char* /* type_name */) { +int cppyy_is_enum(const char* type_name) { + if (strcmp(type_name, "CppyyTestData::EWhat") == 0) + return 1; return 0; } diff --git a/pypy/module/cppyy/test/Makefile b/pypy/module/cppyy/test/Makefile --- a/pypy/module/cppyy/test/Makefile +++ b/pypy/module/cppyy/test/Makefile @@ -29,7 +29,7 @@ endif ifeq ($(DUMMY),t) - cppflags2=-O3 -fPIC -rdynamic + cppflags2=-O3 -fPIC -rdynamic -std=c++11 -DCPPYY_DUMMY_BACKEND else ifeq ($(CLING),t) cppflags2=-O3 -fPIC -rdynamic else @@ -55,7 +55,7 @@ else # reflex %Dict.so: %_rflx.cpp %.cxx - g++ -o $@ $^ -shared -std=c++14 $(cppflags) $(cppflags2) + g++ -o $@ $^ -shared $(cppflags) $(cppflags2) %_rflx.cpp: %.h %.xml $(genreflex) $< $(genreflexflags) --selection=$*.xml --rootmap=$*Dict.rootmap --rootmap-lib=$*Dict.so @@ -66,7 +66,7 @@ # TODO: methptrgetter causes these tests to crash, so don't use it for now std_streamsDict.so: std_streams.cxx std_streams.h std_streams.xml $(genreflex) std_streams.h --selection=std_streams.xml - g++ -o $@ std_streams_rflx.cpp std_streams.cxx -shared -std=c++14 $(cppflags) $(cppflags2) + g++ -o $@ std_streams_rflx.cpp std_streams.cxx -shared -std=c++11 $(cppflags) $(cppflags2) endif .PHONY: clean diff --git a/pypy/module/cppyy/test/conftest.py b/pypy/module/cppyy/test/conftest.py --- a/pypy/module/cppyy/test/conftest.py +++ b/pypy/module/cppyy/test/conftest.py @@ -50,7 +50,8 @@ eci = ExternalCompilationInfo( separate_module_files=[srcpath.join('dummy_backend.cxx')], include_dirs=[incpath, tstpath, cdir], - compile_extra=['-DRPY_EXTERN=RPY_EXPORTED'], + compile_extra=['-DRPY_EXTERN=RPY_EXPORTED', '-DCPPYY_DUMMY_BACKEND', + '-fno-strict-aliasing', '-std=c++11'], use_cpp_linker=True, ) diff --git a/pypy/module/cppyy/test/datatypes.h b/pypy/module/cppyy/test/datatypes.h --- a/pypy/module/cppyy/test/datatypes.h +++ b/pypy/module/cppyy/test/datatypes.h @@ -1,4 +1,15 @@ +#ifndef CPPYY_DUMMY_BACKEND #include "RtypesCore.h" +#else +// copied from RtypesCore.h ... +#if defined(R__WIN32) && !defined(__CINT__) +typedef __int64 Long64_t; //Portable signed long integer 8 bytes +typedef unsigned __int64 ULong64_t; //Portable unsigned long integer 8 bytes +#else +typedef long long Long64_t; //Portable signed long integer 8 bytes +typedef unsigned long long ULong64_t;//Portable unsigned long integer 8 bytes +#endif +#endif #include <vector> const int N = 5; diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py --- a/pypy/module/cppyy/test/test_zjit.py +++ b/pypy/module/cppyy/test/test_zjit.py @@ -157,13 +157,13 @@ assert isinstance(w_obj, FakeFloat) return w_obj.val + @specialize.arg(1) def interp_w(self, RequiredClass, w_obj, can_be_None=False): if can_be_None and w_obj is None: return None if not isinstance(w_obj, RequiredClass): raise TypeError return w_obj - interp_w._annspecialcase_ = 'specialize:arg(1)' def getarg_w(self, code, w_obj): # for retrieving buffers return FakeBuffer(w_obj) diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -36,8 +36,6 @@ from rpython.rlib.objectmodel import specialize from pypy.module import exceptions from pypy.module.exceptions import interp_exceptions -# CPython 2.4 compatibility -from py.builtin import BaseException from rpython.tool.sourcetools import func_with_new_name from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib import rawrefcount @@ -985,7 +983,7 @@ py_type_ready(space, get_capsule_type()) INIT_FUNCTIONS.append(init_types) from pypy.module.posix.interp_posix import add_fork_hook - _reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], + _reinit_tls = rffi.llexternal('%sThread_ReInitTLS' % prefix, [], lltype.Void, compilation_info=eci) def reinit_tls(space): _reinit_tls() @@ -1614,9 +1612,8 @@ miniglobals = {'__name__': __name__, # for module name propagation } exec source.compile() in miniglobals - call_external_function = miniglobals['cpy_call_external'] + call_external_function = specialize.ll()(miniglobals['cpy_call_external']) call_external_function._dont_inline_ = True - call_external_function._annspecialcase_ = 'specialize:ll' call_external_function._gctransformer_hint_close_stack_ = True # don't inline, as a hack to guarantee that no GC pointer is alive # anywhere in call_external_function diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py --- a/pypy/module/cpyext/dictobject.py +++ b/pypy/module/cpyext/dictobject.py @@ -137,8 +137,7 @@ """This is the same as PyDict_Merge(a, b, 1) in C, or a.update(b) in Python. Return 0 on success or -1 if an exception was raised. """ - space.call_method(space.w_dict, "update", w_obj, w_other) - return 0 + return PyDict_Merge(space, w_obj, w_other, 1) @cpython_api([PyObject], PyObject) def PyDict_Keys(space, w_obj): diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py --- a/pypy/module/cpyext/listobject.py +++ b/pypy/module/cpyext/listobject.py @@ -62,12 +62,14 @@ position must be positive, indexing from the end of the list is not supported. If pos is out of bounds, return NULL and set an IndexError exception.""" + from pypy.module.cpyext.sequence import CPyListStrategy if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): raise oefmt(space.w_IndexError, "list index out of range") - w_list.ensure_object_strategy() # make sure we can return a borrowed obj - # XXX ^^^ how does this interact with CPyListStrategy? + cpy_strategy = space.fromcache(CPyListStrategy) + if w_list.strategy is not cpy_strategy: + w_list.ensure_object_strategy() # make sure we can return a borrowed obj w_res = w_list.getitem(index) return w_res # borrowed ref diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py --- a/pypy/module/cpyext/modsupport.py +++ b/pypy/module/cpyext/modsupport.py @@ -1,7 +1,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import cpython_api, cpython_struct, \ METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, CONST_STRING -from pypy.module.cpyext.pyobject import PyObject +from pypy.module.cpyext.pyobject import PyObject, as_pyobj from pypy.interpreter.module import Module from pypy.module.cpyext.methodobject import ( W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod, @@ -124,11 +124,17 @@ else: PyErr_BadInternalCall(space) -@cpython_api([PyObject], rffi.CCHARP, error=0) -def PyModule_GetName(space, module): +@cpython_api([PyObject], rffi.CCHARP) +def PyModule_GetName(space, w_mod): """ Return module's __name__ value. If the module does not provide one, - or if it is not a string, SystemError is raised and NULL is returned.""" - raise NotImplementedError - - + or if it is not a string, SystemError is raised and NULL is returned. + """ + # NOTE: this version of the code works only because w_mod.w_name is + # a wrapped string object attached to w_mod; so it makes a + # PyStringObject that will live as long as the module itself, + # and returns a "char *" inside this PyStringObject. + if not isinstance(w_mod, Module): + raise oefmt(space.w_SystemError, "PyModule_GetName(): not a module") + from pypy.module.cpyext.bytesobject import PyString_AsString + return PyString_AsString(space, as_pyobj(space, w_mod.w_name)) diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -15,6 +15,7 @@ from rpython.rlib.objectmodel import keepalive_until_here from rpython.rtyper.annlowlevel import llhelper from rpython.rlib import rawrefcount +from rpython.rlib.debug import fatalerror #________________________________________________________ @@ -24,11 +25,9 @@ basestruct = PyObject.TO W_BaseObject = W_ObjectObject - def get_dealloc(self, space): + def get_dealloc(self): from pypy.module.cpyext.typeobject import subtype_dealloc - return llhelper( - subtype_dealloc.api_func.functype, - subtype_dealloc.api_func.get_wrapper(space)) + return subtype_dealloc.api_func def allocate(self, space, w_type, itemcount=0): # similar to PyType_GenericAlloc? @@ -108,10 +107,8 @@ return tp_alloc(space, w_type, itemcount) if tp_dealloc: - def get_dealloc(self, space): - return llhelper( - tp_dealloc.api_func.functype, - tp_dealloc.api_func.get_wrapper(space)) + def get_dealloc(self): + return tp_dealloc.api_func if tp_attach: def attach(self, space, pyobj, w_obj): @@ -192,6 +189,8 @@ rawrefcount.create_link_pypy(w_obj, py_obj) +w_marker_deallocating = W_Root() + def from_ref(space, ref): """ Finds the interpreter object corresponding to the given reference. If the @@ -202,7 +201,23 @@ return None w_obj = rawrefcount.to_obj(W_Root, ref) if w_obj is not None: - return w_obj + if w_obj is not w_marker_deallocating: + return w_obj + fatalerror( + "*** Invalid usage of a dying CPython object ***\n" + "\n" + "cpyext, the emulation layer, detected that while it is calling\n" + "an object's tp_dealloc, the C code calls back a function that\n" + "tries to recreate the PyPy version of the object. Usually it\n" + "means that tp_dealloc calls some general PyXxx() API. It is\n" + "a dangerous and potentially buggy thing to do: even in CPython\n" + "the PyXxx() function could, in theory, cause a reference to the\n" + "object to be taken and stored somewhere, for an amount of time\n" + "exceeding tp_dealloc itself. Afterwards, the object will be\n" + "freed, making that reference point to garbage.\n" + ">>> PyPy could contain some workaround to still work if\n" + "you are lucky, but it is not done so far; better fix the bug in\n" + "the CPython extension.") # This reference is not yet a real interpreter object. # Realize it. @@ -233,7 +248,8 @@ INTERPLEVEL_API['as_pyobj'] = as_pyobj def pyobj_has_w_obj(pyobj): - return rawrefcount.to_obj(W_Root, pyobj) is not None + w_obj = rawrefcount.to_obj(W_Root, pyobj) + return w_obj is not None and w_obj is not w_marker_deallocating INTERPLEVEL_API['pyobj_has_w_obj'] = staticmethod(pyobj_has_w_obj) @@ -335,6 +351,7 @@ pto = obj.c_ob_type #print >>sys.stderr, "Calling dealloc slot", pto.c_tp_dealloc, "of", obj, \ # "'s type which is", rffi.charp2str(pto.c_tp_name) + rawrefcount.mark_deallocating(w_marker_deallocating, obj) generic_cpy_call(space, pto.c_tp_dealloc, obj) @cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL) diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -8,12 +8,12 @@ cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES, mangle_name, pypy_decl, Py_buffer, Py_bufferP) from pypy.module.cpyext.typeobjectdefs import ( - unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, ternaryfunc, + unaryfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, readbufferproc, getbufferproc, ssizessizeobjargproc) -from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef +from pypy.module.cpyext.pyobject import make_ref, Py_DecRef from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.memoryobject import fill_Py_buffer from pypy.module.cpyext.state import State @@ -21,8 +21,10 @@ from pypy.interpreter.argument import Arguments from rpython.rlib.buffer import Buffer from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.objectmodel import specialize +from rpython.rlib.objectmodel import specialize, not_rpython from rpython.tool.sourcetools import func_renamer +from rpython.flowspace.model import Constant +from rpython.flowspace.specialcase import register_flow_sc from rpython.rtyper.annlowlevel import llhelper from pypy.module.sys.version import CPYTHON_VERSION @@ -59,6 +61,17 @@ "expected %d-%d arguments, got %d", low, high, space.len_w(w_ob)) +@not_rpython +def llslot(space, func): + return llhelper(func.api_func.functype, func.api_func.get_wrapper(space)) + +@register_flow_sc(llslot) +def sc_llslot(ctx, v_space, v_func): + assert isinstance(v_func, Constant) + get_llhelper = v_func.value.api_func.get_llhelper + return ctx.appcall(get_llhelper, v_space) + + def wrap_init(space, w_self, w_args, func, w_kwargs): func_init = rffi.cast(initproc, func) res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) @@ -106,7 +119,7 @@ args_w = space.fixedview(w_args) arg3 = space.w_None if len(args_w) > 1: - arg3 = args_w[1] + arg3 = args_w[1] return generic_cpy_call(space, func_ternary, w_self, args_w[0], arg3) def wrap_ternaryfunc_r(space, w_self, w_args, func): @@ -121,7 +134,7 @@ Py_DecRef(space, ref) arg3 = space.w_None if len(args_w) > 1: - arg3 = args_w[1] + arg3 = args_w[1] return generic_cpy_call(space, func_ternary, args_w[0], w_self, arg3) @@ -322,7 +335,7 @@ self.strides = [1] else: self.strides = strides - self.ndim = ndim + self.ndim = ndim self.itemsize = itemsize self.readonly = readonly @@ -437,9 +450,10 @@ try: return SLOTS[key] except KeyError: - ret = build_slot_tp_function(space, typedef, name) - SLOTS[key] = ret - return ret + slot_func = build_slot_tp_function(space, typedef, name) + api_func = slot_func.api_func if slot_func else None + SLOTS[key] = api_func + return api_func def build_slot_tp_function(space, typedef, name): w_type = space.gettypeobject(typedef) @@ -472,7 +486,6 @@ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) def slot_func(space, w_self): return space.call_function(slot_fn, w_self) - api_func = slot_func.api_func handled = True # binary functions @@ -499,7 +512,6 @@ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) def slot_func(space, w_self, w_arg): return space.call_function(slot_fn, w_self, w_arg) - api_func = slot_func.api_func handled = True # binary-with-Py_ssize_t-type @@ -517,7 +529,6 @@ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) def slot_func(space, w_self, arg): return space.call_function(slot_fn, w_self, space.wrap(arg)) - api_func = slot_func.api_func handled = True # ternary functions @@ -532,7 +543,6 @@ @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) def slot_func(space, w_self, w_arg1, w_arg2): return space.call_function(slot_fn, w_self, w_arg1, w_arg2) - api_func = slot_func.api_func handled = True if handled: @@ -552,7 +562,7 @@ else: space.call_function(delattr_fn, w_self, w_name) return 0 - api_func = slot_tp_setattro.api_func + slot_func = slot_tp_setattro elif name == 'tp_getattro': getattr_fn = w_type.getdictvalue(space, '__getattribute__') if getattr_fn is None: @@ -562,7 +572,7 @@ @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,)) def slot_tp_getattro(space, w_self, w_name): return space.call_function(getattr_fn, w_self, w_name) - api_func = slot_tp_getattro.api_func + slot_func = slot_tp_getattro elif name == 'tp_call': call_fn = w_type.getdictvalue(space, '__call__') if call_fn is None: @@ -574,7 +584,7 @@ args = Arguments(space, [w_self], w_stararg=w_args, w_starstararg=w_kwds) return space.call_args(call_fn, args) - api_func = slot_tp_call.api_func + slot_func = slot_tp_call elif name == 'tp_iternext': iternext_fn = w_type.getdictvalue(space, 'next') @@ -590,7 +600,7 @@ if not e.match(space, space.w_StopIteration): raise return None - api_func = slot_tp_iternext.api_func + slot_func = slot_tp_iternext elif name == 'tp_init': init_fn = w_type.getdictvalue(space, '__init__') @@ -605,7 +615,7 @@ w_stararg=w_args, w_starstararg=w_kwds) space.call_args(init_fn, args) return 0 - api_func = slot_tp_init.api_func + slot_func = slot_tp_init elif name == 'tp_new': new_fn = w_type.getdictvalue(space, '__new__') if new_fn is None: @@ -617,12 +627,12 @@ args = Arguments(space, [w_self], w_stararg=w_args, w_starstararg=w_kwds) return space.call_args(space.get(new_fn, w_self), args) - api_func = slot_tp_new.api_func + slot_func = slot_tp_new elif name == 'tp_as_buffer.c_bf_getbuffer': buff_fn = w_type.getdictvalue(space, '__buffer__') if buff_fn is None: return - @cpython_api([PyObject, Py_bufferP, rffi.INT_real], + @cpython_api([PyObject, Py_bufferP, rffi.INT_real], rffi.INT_real, header=None, error=-1) @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) def buff_w(space, w_self, view, flags): @@ -646,14 +656,14 @@ return 0 # XXX remove this when it no longer crashes a translated PyPy return - api_func = buff_w.api_func + slot_func = buff_w else: # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce # tp_as_sequence.c_sq_contains, tp_as_sequence.c_sq_length # richcmpfunc(s) return - return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) + return slot_func PyWrapperFlag_KEYWORDS = 1 @@ -984,8 +994,8 @@ slotdefs = sorted(slotdefs, key=slotdef_sort_key) slotdefs_for_tp_slots = unrolling_iterable( - [(x.method_name, x.slot_name, x.slot_names, x.slot_func) - for x in slotdefs]) + [(x.method_name, x.slot_name, x.slot_names, + x.slot_func.api_func if x.slot_func else None) for x in slotdefs]) slotdefs_for_wrappers = unrolling_iterable( [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc) diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py --- a/pypy/module/cpyext/test/test_dictobject.py _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit