[pypy-commit] pypy numpy-pickle: Merge default
rguillebert
noreply at buildbot.pypy.org
Thu May 23 18:38:27 CEST 2013
Author: Romain Guillebert <romain.py at gmail.com>
Branch: numpy-pickle
Changeset: r64514:75782b4f223f
Date: 2013-05-23 17:29 +0200
http://bitbucket.org/pypy/pypy/changeset/75782b4f223f/
Log: Merge default
diff too long, truncating to 2000 out of 12012 lines
diff --git a/lib-python/2.7/distutils/sysconfig.py b/lib-python/2.7/distutils/sysconfig.py
--- a/lib-python/2.7/distutils/sysconfig.py
+++ b/lib-python/2.7/distutils/sysconfig.py
@@ -1,30 +1,16 @@
-"""Provide access to Python's configuration information. The specific
-configuration variables available depend heavily on the platform and
-configuration. The values may be retrieved using
-get_config_var(name), and the list of variables is available via
-get_config_vars().keys(). Additional convenience functions are also
-available.
-
-Written by: Fred L. Drake, Jr.
-Email: <fdrake at acm.org>
-"""
-
-__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
-
-import sys
-
# The content of this file is redirected from
# sysconfig_cpython or sysconfig_pypy.
+# All underscore names are imported too, because
+# people like to use undocumented sysconfig._xxx
+# directly.
+import sys
if '__pypy__' in sys.builtin_module_names:
- from distutils.sysconfig_pypy import *
- from distutils.sysconfig_pypy import _config_vars # needed by setuptools
- from distutils.sysconfig_pypy import _variable_rx # read_setup_file()
+ from distutils import sysconfig_pypy as _sysconfig_module
else:
- from distutils.sysconfig_cpython import *
- from distutils.sysconfig_cpython import _config_vars # needed by setuptools
- from distutils.sysconfig_cpython import _variable_rx # read_setup_file()
+ from distutils import sysconfig_cpython as _sysconfig_module
+globals().update(_sysconfig_module.__dict__)
_USE_CLANG = None
diff --git a/lib-python/2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py
--- a/lib-python/2.7/distutils/sysconfig_cpython.py
+++ b/lib-python/2.7/distutils/sysconfig_cpython.py
@@ -9,7 +9,7 @@
Email: <fdrake at acm.org>
"""
-__revision__ = "$Id$"
+__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
import os
import re
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
@@ -1,6 +1,15 @@
-"""PyPy's minimal configuration information.
+"""Provide access to Python's configuration information.
+This is actually PyPy's minimal configuration information.
+
+The specific configuration variables available depend heavily on the
+platform and configuration. The values may be retrieved using
+get_config_var(name), and the list of variables is available via
+get_config_vars().keys(). Additional convenience functions are also
+available.
"""
+__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
+
import sys
import os
import imp
diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -324,7 +324,12 @@
if self._close:
self._sock.close()
else:
- self._sock._decref_socketios()
+ try:
+ self._sock._decref_socketios()
+ except AttributeError:
+ pass # bah, someone built a _fileobject manually
+ # with some unexpected replacement of the
+ # _socketobject class
self._sock = None
def __del__(self):
diff --git a/lib-python/2.7/test/test_codecs.py b/lib-python/2.7/test/test_codecs.py
--- a/lib-python/2.7/test/test_codecs.py
+++ b/lib-python/2.7/test/test_codecs.py
@@ -2,7 +2,11 @@
import unittest
import codecs
import locale
-import sys, StringIO, _testcapi
+import sys, StringIO
+try:
+ import _testcapi
+except ImportError:
+ _testcapi = None
class Queue(object):
"""
@@ -1387,7 +1391,7 @@
decodedresult += reader.read()
self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding))
- if encoding not in broken_incremental_coders:
+ if encoding not in broken_incremental_coders and _testcapi:
# check incremental decoder/encoder (fetched via the Python
# and C API) and iterencode()/iterdecode()
try:
diff --git a/lib-python/2.7/test/test_sysconfig.py b/lib-python/2.7/test/test_sysconfig.py
--- a/lib-python/2.7/test/test_sysconfig.py
+++ b/lib-python/2.7/test/test_sysconfig.py
@@ -7,7 +7,8 @@
import subprocess
from copy import copy, deepcopy
-from test.test_support import run_unittest, TESTFN, unlink, get_attribute
+from test.test_support import (run_unittest, TESTFN, unlink, get_attribute,
+ import_module)
import sysconfig
from sysconfig import (get_paths, get_platform, get_config_vars,
@@ -236,7 +237,10 @@
def test_get_config_h_filename(self):
config_h = sysconfig.get_config_h_filename()
- self.assertTrue(os.path.isfile(config_h), config_h)
+ # import_module skips the test when the CPython C Extension API
+ # appears to not be supported
+ self.assertTrue(os.path.isfile(config_h) or
+ not import_module('_testcapi'), config_h)
def test_get_scheme_names(self):
wanted = ('nt', 'nt_user', 'os2', 'os2_home', 'osx_framework_user',
diff --git a/lib-python/2.7/test/test_traceback.py b/lib-python/2.7/test/test_traceback.py
--- a/lib-python/2.7/test/test_traceback.py
+++ b/lib-python/2.7/test/test_traceback.py
@@ -1,6 +1,9 @@
"""Test cases for traceback module"""
-from _testcapi import traceback_print
+try:
+ from _testcapi import traceback_print
+except ImportError:
+ traceback_print = None
from StringIO import StringIO
import sys
import unittest
@@ -176,6 +179,8 @@
class TracebackFormatTests(unittest.TestCase):
def test_traceback_format(self):
+ if traceback_print is None:
+ raise unittest.SkipTest('Requires _testcapi')
try:
raise KeyError('blah')
except KeyError:
diff --git a/lib-python/2.7/test/test_unicode.py b/lib-python/2.7/test/test_unicode.py
--- a/lib-python/2.7/test/test_unicode.py
+++ b/lib-python/2.7/test/test_unicode.py
@@ -1609,7 +1609,10 @@
self.assertEqual("{}".format(u), '__unicode__ overridden')
def test_encode_decimal(self):
- from _testcapi import unicode_encodedecimal
+ try:
+ from _testcapi import unicode_encodedecimal
+ except ImportError:
+ raise unittest.SkipTest('Requires _testcapi')
self.assertEqual(unicode_encodedecimal(u'123'),
b'123')
self.assertEqual(unicode_encodedecimal(u'\u0663.\u0661\u0664'),
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -130,7 +130,7 @@
RegrTest('test_bz2.py', usemodules='bz2'),
RegrTest('test_calendar.py'),
RegrTest('test_call.py', core=True),
- RegrTest('test_capi.py'),
+ RegrTest('test_capi.py', usemodules='cpyext'),
RegrTest('test_cd.py'),
RegrTest('test_cfgparser.py'),
RegrTest('test_cgi.py'),
@@ -177,7 +177,7 @@
RegrTest('test_cprofile.py'),
RegrTest('test_crypt.py', usemodules='crypt'),
RegrTest('test_csv.py', usemodules='_csv'),
- RegrTest('test_ctypes.py', usemodules="_rawffi thread"),
+ RegrTest('test_ctypes.py', usemodules="_rawffi thread cpyext"),
RegrTest('test_curses.py'),
RegrTest('test_datetime.py', usemodules='binascii struct'),
RegrTest('test_dbm.py'),
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -54,4 +54,9 @@
fp, filename, description = imp.find_module('_testcapi', path=[output_dir])
imp.load_module('_testcapi', fp, filename, description)
-compile_shared()
+try:
+ import cpyext
+except ImportError:
+ raise ImportError("No module named '_testcapi'")
+else:
+ compile_shared()
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -121,12 +121,10 @@
__import__(name)
except (ImportError, CompilationError, py.test.skip.Exception), e:
errcls = e.__class__.__name__
- config.add_warning(
+ raise Exception(
"The module %r is disabled\n" % (modname,) +
"because importing %s raised %s\n" % (name, errcls) +
str(e))
- raise ConflictConfigError("--withmod-%s: %s" % (modname,
- errcls))
return validator
else:
return None
@@ -217,10 +215,6 @@
"(the empty string and potentially single-char strings)",
default=False),
- BoolOption("withsmalltuple",
- "use small tuples",
- default=False),
-
BoolOption("withspecialisedtuple",
"use specialised tuples",
default=False),
@@ -365,6 +359,7 @@
# ignore names from 'essential_modules', notably 'exceptions', which
# may not be present in config.objspace.usemodules at all
modules = [name for name in modules if name not in essential_modules]
+
config.objspace.usemodules.suggest(**dict.fromkeys(modules, True))
def enable_translationmodules(config):
diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -339,8 +339,9 @@
+ methods and other class attributes do not change after startup
+ single inheritance is fully supported
-+ simple mixins work too, but the mixed in class needs a ``_mixin_ = True``
- class attribute
++ simple mixins somewhat work too, but the mixed in class needs a
+ ``_mixin_ = True`` class attribute. isinstance checks against the
+ mixin type will fail when translated.
+ classes are first-class objects too
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -47,7 +47,7 @@
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
-release = '2.0.0'
+release = '2.0.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/pypy/doc/how-to-contribute.rst b/pypy/doc/how-to-contribute.rst
--- a/pypy/doc/how-to-contribute.rst
+++ b/pypy/doc/how-to-contribute.rst
@@ -28,7 +28,8 @@
Layers
------
-PyPy has layers. Those layers help us keep the respective parts separated enough
+PyPy has layers. Just like Ogres or onions.
+Those layers help us keep the respective parts separated enough
to be worked on independently and make the complexity manageable. This is,
again, just a sanity requirement for such a complex project. For example writing
a new optimization for the JIT usually does **not** involve touching a Python
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -22,7 +22,8 @@
will capture the revision number of this change for the release;
some of the next updates may be done before or after branching; make
sure things are ported back to the trunk and to the branch as
- necessary
+ necessary; also update the version number in pypy/doc/conf.py,
+ and in pypy/doc/index.rst
* update pypy/doc/contributor.rst (and possibly LICENSE)
* rename pypy/doc/whatsnew_head.rst to whatsnew_VERSION.rst
and create a fresh whatsnew_head.rst after the release
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -40,7 +40,7 @@
* `FAQ`_: some frequently asked questions.
-* `Release 2.0`_: the latest official release
+* `Release 2.0.2`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -110,7 +110,7 @@
.. _`Getting Started`: getting-started.html
.. _`Papers`: extradoc.html
.. _`Videos`: video-index.html
-.. _`Release 2.0`: http://pypy.org/download.html
+.. _`Release 2.0.2`: http://pypy.org/download.html
.. _`speed.pypy.org`: http://speed.pypy.org
.. _`RPython toolchain`: translation.html
.. _`potential project ideas`: project-ideas.html
diff --git a/pypy/doc/release-2.0.1.rst b/pypy/doc/release-2.0.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.0.1.rst
@@ -0,0 +1,46 @@
+==============================
+PyPy 2.0.1 - Bohr Smørrebrød
+==============================
+
+We're pleased to announce PyPy 2.0.1. This is a stable bugfix release
+over `2.0`_. You can download it here:
+
+ http://pypy.org/download.html
+
+The fixes are mainly about fatal errors or crashes in our stdlib. See
+below for more details.
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.0 and cpython 2.7.3`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32. Support for ARM is progressing but not bug-free yet.
+
+.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
+
+Highlights
+==========
+
+- fix an occasional crash in the JIT that ends in `RPython Fatal error:
+ NotImplementedError`__.
+
+- `id(x)` is now always a positive number (except on int/float/long/complex).
+ This fixes an issue in ``_sqlite.py`` (mostly for 32-bit Linux).
+
+- fix crashes of callback-from-C-functions (with cffi) when used together
+ with Stackless features, on asmgcc (i.e. Linux only). Now `gevent should
+ work better`__.
+
+- work around an eventlet issue with `socket._decref_socketios()`__.
+
+.. __: https://bugs.pypy.org/issue1482
+.. __: http://mail.python.org/pipermail/pypy-dev/2013-May/011362.html
+.. __: https://bugs.pypy.org/issue1468
+.. _2.0: release-2.0.0.html
+
+Cheers,
+arigo et. al. for the PyPy team
diff --git a/pypy/doc/release-2.0.2.rst b/pypy/doc/release-2.0.2.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.0.2.rst
@@ -0,0 +1,46 @@
+=========================
+PyPy 2.0.2 - Fermi Panini
+=========================
+
+We're pleased to announce PyPy 2.0.2. This is a stable bugfix release
+over `2.0`_ and `2.0.1`_. You can download it here:
+
+ http://pypy.org/download.html
+
+It fixes a crash in the JIT when calling external C functions (with
+ctypes/cffi) in a multithreaded context.
+
+.. _2.0: release-2.0.0.html
+.. _2.0.1: release-2.0.1.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.0 and cpython 2.7.3`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32. Support for ARM is progressing but not bug-free yet.
+
+.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
+
+Highlights
+==========
+
+This release contains only the fix described above. A crash (or wrong
+results) used to occur if all these conditions were true:
+
+- your program is multithreaded;
+
+- it runs on a single-core machine or a heavily-loaded multi-core one;
+
+- it uses ctypes or cffi to issue external calls to C functions.
+
+This was fixed in the branch `emit-call-x86`__ (see the example file
+``bug1.py``).
+
+.. __: https://bitbucket.org/pypy/pypy/commits/7c80121abbf4
+
+Cheers,
+arigo et. al. for the PyPy team
diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py
--- a/pypy/doc/test/test_whatsnew.py
+++ b/pypy/doc/test/test_whatsnew.py
@@ -19,23 +19,28 @@
branches.discard('default')
return startrev, branches
-def get_merged_branches(path, startrev, endrev):
- if getstatusoutput('hg root')[0]:
+def get_merged_branches(path, startrev, endrev, current_branch=None):
+ errcode, wc_branch = getstatusoutput('hg branch')
+ if errcode != 0:
py.test.skip('no Mercurial repo')
+ if current_branch is None:
+ current_branch = wc_branch
# X = take all the merges which are descendants of startrev and are on default
# revset = all the parents of X which are not on default
# ===>
# revset contains all the branches which have been merged to default since
# startrev
- revset = 'parents(%s::%s and \
+ revset = "parents(%s::%s and \
merge() and \
- branch(default)) and \
- not branch(default)' % (startrev, endrev)
+ branch('%s')) and \
+ not branch('%s')" % (startrev, endrev,
+ current_branch, current_branch)
cmd = r'hg log -R "%s" -r "%s" --template "{branches}\n"' % (path, revset)
out = getoutput(cmd)
branches = set(map(str.strip, out.splitlines()))
- return branches
+ branches.discard("default")
+ return branches, current_branch
def test_parse_doc():
@@ -65,7 +70,8 @@
assert branches == set(['foobar', 'hello'])
def test_get_merged_branches():
- branches = get_merged_branches(ROOT, 'f34f0c11299f', '79770e0c2f93')
+ branches, _ = get_merged_branches(ROOT, 'f34f0c11299f', '79770e0c2f93',
+ 'default')
assert branches == set(['numpy-indexing-by-arrays-bool',
'better-jit-hooks-2',
'numpypy-ufuncs'])
@@ -76,7 +82,9 @@
whatsnew_list.sort()
last_whatsnew = whatsnew_list[-1].read()
startrev, documented = parse_doc(last_whatsnew)
- merged = get_merged_branches(ROOT, startrev, '')
+ merged, branch = get_merged_branches(ROOT, startrev, '')
+ merged.discard('default')
+ merged.discard('')
not_documented = merged.difference(documented)
not_merged = documented.difference(merged)
print 'Branches merged but not documented:'
@@ -85,4 +93,6 @@
print 'Branches documented but not merged:'
print '\n'.join(not_merged)
print
- assert not not_documented and not not_merged
+ assert not not_documented
+ if branch == 'default':
+ assert not not_merged
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
@@ -8,5 +8,29 @@
.. branch: numpy-pickle
Pickling of numpy arrays and dtypes (including record dtypes)
+.. branch: remove-array-smm
+Remove multimethods in the arraymodule
+
+.. branch: callback-stacklet
+Fixed bug when switching stacklets from a C callback
+
+.. branch: remove-set-smm
+Remove multi-methods on sets
+
.. branch: numpy-subarrays
-It is now possible to create arrays and dtypes that use subarrays
+Implement subarrays for numpy
+
+.. branch: remove-dict-smm
+Remove multi-methods on dict
+
+.. branch: remove-list-smm-2
+Remove remaining multi-methods on list
+
+.. branch: arm-stacklet
+Stacklet support for ARM, enables _continuation support
+
+.. branch: remove-tuple-smm
+Remove multi-methods on tuple
+
+.. branch: remove-iter-smm
+Remove multi-methods on iterators
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -10,6 +10,8 @@
from rpython.config.config import ConflictConfigError
from pypy.tool.option import make_objspace
from pypy.conftest import pypydir
+from rpython.rlib import rthread
+from pypy.module.thread import os_thread
thisdir = py.path.local(__file__).dirpath()
@@ -120,6 +122,17 @@
source = rffi.charp2str(ll_source)
return _pypy_execute_source(source)
+ @entrypoint('main', [], c_name='pypy_init_threads')
+ def pypy_init_threads():
+ if space.config.objspace.usemodules.thread:
+ os_thread.setup_threads(space)
+ rffi.aroundstate.before()
+
+ @entrypoint('main', [], c_name='pypy_thread_attach')
+ def pypy_thread_attach():
+ if space.config.objspace.usemodules.thread:
+ rthread.gc_thread_start()
+
w_globals = space.newdict()
space.setitem(w_globals, space.wrap('__builtins__'),
space.builtin_modules['__builtin__'])
@@ -137,6 +150,8 @@
return 0
return entry_point, {'pypy_execute_source': pypy_execute_source,
+ 'pypy_init_threads': pypy_init_threads,
+ 'pypy_thread_attach': pypy_thread_attach,
'pypy_setup_home': pypy_setup_home}
def call_finish(space):
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -853,9 +853,10 @@
self.emit_jump(ops.JUMP_IF_FALSE_OR_POP, cleanup, True)
if i < (ops_count - 1):
comp.comparators[i].walkabout(self)
- comp.comparators[-1].walkabout(self)
- last_kind = compare_operations(comp.ops[-1])
- self.emit_op_arg(ops.COMPARE_OP, last_kind)
+ last_op, last_comparator = comp.ops[-1], comp.comparators[-1]
+ if not self._optimize_comparator(last_op, last_comparator):
+ last_comparator.walkabout(self)
+ self.emit_op_arg(ops.COMPARE_OP, compare_operations(last_op))
if ops_count > 1:
end = self.new_block()
self.emit_jump(ops.JUMP_FORWARD, end)
@@ -864,6 +865,37 @@
self.emit_op(ops.POP_TOP)
self.use_next_block(end)
+ def _optimize_comparator(self, op, node):
+ """Fold lists/sets of constants in the context of "in"/"not in".
+
+ lists are folded into tuples, sets into frozensets, otherwise
+ returns False
+ """
+ if op in (ast.In, ast.NotIn):
+ is_list = isinstance(node, ast.List)
+ if is_list or isinstance(node, ast.Set):
+ w_const = self._tuple_of_consts(node.elts)
+ if w_const is not None:
+ if not is_list:
+ from pypy.objspace.std.setobject import (
+ W_FrozensetObject)
+ w_const = W_FrozensetObject(self.space, w_const)
+ self.load_const(w_const)
+ return True
+ return False
+
+ def _tuple_of_consts(self, elts):
+ """Return a tuple of consts from elts if possible, or None"""
+ count = len(elts) if elts is not None else 0
+ consts_w = [None] * count
+ for i in range(count):
+ w_value = elts[i].as_constant()
+ if w_value is None:
+ # Not all constants
+ return None
+ consts_w[i] = w_value
+ return self.space.newtuple(consts_w)
+
def visit_IfExp(self, ifexp):
self.update_position(ifexp.lineno)
end = self.new_block()
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -973,3 +973,30 @@
counts = self.count_instructions(source3)
assert counts[ops.BUILD_LIST] == 1
assert ops.BUILD_LIST_FROM_ARG not in counts
+
+ def test_folding_of_list_constants(self):
+ for source in (
+ # in/not in constants with BUILD_LIST should be folded to a tuple:
+ 'a in [1,2,3]',
+ 'a not in ["a","b","c"]',
+ 'a in [None, 1, None]',
+ 'a not in [(1, 2), 3, 4]',
+ ):
+ source = 'def f(): %s' % source
+ counts = self.count_instructions(source)
+ assert ops.BUILD_LIST not in counts
+ assert ops.LOAD_CONST in counts
+
+ def test_folding_of_set_constants(self):
+ for source in (
+ # in/not in constants with BUILD_SET should be folded to a frozenset:
+ 'a in {1,2,3}',
+ 'a not in {"a","b","c"}',
+ 'a in {None, 1, None}',
+ 'a not in {(1, 2), 3, 4}',
+ 'a in {1, 2, 3, 3, 2, 1}',
+ ):
+ source = 'def f(): %s' % source
+ counts = self.count_instructions(source)
+ assert ops.BUILD_SET not in counts
+ assert ops.LOAD_CONST in counts
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -242,6 +242,11 @@
def __spacebind__(self, space):
return self
+ def unwrap(self, space):
+ """NOT_RPYTHON"""
+ # _____ this code is here to support testing only _____
+ return self
+
class W_InterpIterable(W_Root):
def __init__(self, space, w_iterable):
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -903,22 +903,33 @@
expected_path = [str(prefix.join(subdir).ensure(dir=1))
for subdir in ('lib_pypy',
'lib-python/%s' % cpy_ver)]
+ # an empty directory from where we can't find the stdlib
+ tmp_dir = str(udir.join('tmp').ensure(dir=1))
self.w_goal_dir = self.space.wrap(goal_dir)
self.w_fake_exe = self.space.wrap(str(fake_exe))
self.w_expected_path = self.space.wrap(expected_path)
self.w_trunkdir = self.space.wrap(os.path.dirname(pypydir))
+ self.w_tmp_dir = self.space.wrap(tmp_dir)
+
foo_py = prefix.join('foo.py').write("pass")
self.w_foo_py = self.space.wrap(str(foo_py))
def test_setup_bootstrap_path(self):
- import sys
+ # Check how sys.path is handled depending on if we can find a copy of
+ # the stdlib in setup_bootstrap_path.
+ import sys, os
old_sys_path = sys.path[:]
+ old_cwd = os.getcwd()
+
sys.path.append(self.goal_dir)
+ # make sure cwd does not contain a stdlib
+ os.chdir(self.tmp_dir)
+ tmp_pypy_c = os.path.join(self.tmp_dir, 'pypy-c')
try:
import app_main
- app_main.setup_bootstrap_path('/tmp/pypy-c') # stdlib not found
+ app_main.setup_bootstrap_path(tmp_pypy_c) # stdlib not found
assert sys.executable == ''
assert sys.path == old_sys_path + [self.goal_dir]
@@ -933,6 +944,7 @@
assert newpath[:len(self.expected_path)] == self.expected_path
finally:
sys.path[:] = old_sys_path
+ os.chdir(old_cwd)
def test_trunk_can_be_prefix(self):
import sys
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
@@ -936,6 +936,21 @@
output = s.getvalue()
assert "LOAD_GLOBAL" not in output
+ def test_folding_of_list_constants(self):
+ source = 'a in [1, 2, 3]'
+ co = compile(source, '', 'exec')
+ i = co.co_consts.index((1, 2, 3))
+ assert i > -1
+ assert isinstance(co.co_consts[i], tuple)
+
+ def test_folding_of_set_constants(self):
+ source = 'a in {1, 2, 3}'
+ co = compile(source, '', 'exec')
+ i = co.co_consts.index(set([1, 2, 3]))
+ assert i > -1
+ assert isinstance(co.co_consts[i], frozenset)
+
+
class AppTestCallMethod(object):
spaceconfig = {'objspace.opcodes.CALL_METHOD': True}
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
@@ -7,7 +7,7 @@
appleveldefs = {
}
interpleveldefs = {
- '__version__': 'space.wrap("0.6")',
+ '__version__': 'space.wrap("0.7")',
'load_library': 'libraryobj.load_library',
@@ -30,6 +30,8 @@
'typeoffsetof': 'func.typeoffsetof',
'rawaddressof': 'func.rawaddressof',
'getcname': 'func.getcname',
+ 'newp_handle': 'handle.newp_handle',
+ 'from_handle': 'handle.from_handle',
'_get_types': 'func._get_types',
'string': 'func.string',
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
@@ -114,8 +114,11 @@
ge = _make_comparison('ge')
def hash(self):
- h = (objectmodel.compute_identity_hash(self.ctype) ^
- rffi.cast(lltype.Signed, self._cdata))
+ h = rffi.cast(lltype.Signed, self._cdata)
+ # To hash pointers in dictionaries. Assumes that h shows some
+ # alignment (to 4, 8, maybe 16 bytes), so we use the following
+ # formula to avoid the trailing bits being always 0.
+ h = h ^ (h >> 4)
return self.space.wrap(h)
def getitem(self, w_index):
@@ -391,6 +394,19 @@
return self.length
+class W_CDataHandle(W_CData):
+ _attrs_ = ['w_keepalive']
+ _immutable_fields_ = ['w_keepalive']
+
+ def __init__(self, space, cdata, ctype, w_keepalive):
+ W_CData.__init__(self, space, cdata, ctype)
+ self.w_keepalive = w_keepalive
+
+ def _repr_extra(self):
+ w_repr = self.space.repr(self.w_keepalive)
+ return "handle to %s" % (self.space.str_w(w_repr),)
+
+
W_CData.typedef = TypeDef(
'CData',
__module__ = '_cffi_backend',
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -172,8 +172,8 @@
class W_CTypePointer(W_CTypePtrBase):
- _attrs_ = ['is_file', 'cache_array_type']
- _immutable_fields_ = ['is_file', 'cache_array_type?']
+ _attrs_ = ['is_file', 'cache_array_type', 'is_void_ptr']
+ _immutable_fields_ = ['is_file', 'cache_array_type?', 'is_void_ptr']
kind = "pointer"
cache_array_type = None
@@ -186,6 +186,7 @@
extra = " *"
self.is_file = (ctitem.name == "struct _IO_FILE" or
ctitem.name == "struct $FILE")
+ self.is_void_ptr = isinstance(ctitem, ctypevoid.W_CTypeVoid)
W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
def newp(self, w_init):
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/handle.py
@@ -0,0 +1,93 @@
+import weakref
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.module._cffi_backend import ctypeobj, ctypeptr, cdataobj
+from pypy.module._weakref.interp__weakref import dead_ref
+from rpython.rtyper.lltypesystem import lltype, rffi
+
+
+def reduced_value(s):
+ while True:
+ divide = s & 1
+ s >>= 1
+ if not divide:
+ return s
+
+# ____________________________________________________________
+
+
+class CffiHandles:
+ def __init__(self, space):
+ self.handles = []
+ self.look_distance = 0
+
+ def reserve_next_handle_index(self):
+ # The reservation ordering done here is tweaked for pypy's
+ # memory allocator. We look from index 'look_distance'.
+ # Look_distance increases from 0. But we also look at
+ # "look_distance/2" or "/4" or "/8", etc. If we find that one
+ # of these secondary locations is free, we assume it's because
+ # there was recently a minor collection; so we reset
+ # look_distance to 0 and start again from the lowest locations.
+ length = len(self.handles)
+ for d in range(self.look_distance, length):
+ if self.handles[d]() is None:
+ self.look_distance = d + 1
+ return d
+ s = reduced_value(d)
+ if self.handles[s]() is None:
+ break
+ # restart from the beginning
+ for d in range(0, length):
+ if self.handles[d]() is None:
+ self.look_distance = d + 1
+ return d
+ # full! extend, but don't use '!=' here
+ self.handles = self.handles + [dead_ref] * (length // 3 + 5)
+ self.look_distance = length + 1
+ return length
+
+ def store_handle(self, index, content):
+ self.handles[index] = weakref.ref(content)
+
+ def fetch_handle(self, index):
+ if 0 <= index < len(self.handles):
+ return self.handles[index]()
+ return None
+
+def get(space):
+ return space.fromcache(CffiHandles)
+
+# ____________________________________________________________
+
+ at unwrap_spec(w_ctype=ctypeobj.W_CType)
+def newp_handle(space, w_ctype, w_x):
+ if (not isinstance(w_ctype, ctypeptr.W_CTypePointer) or
+ not w_ctype.is_void_ptr):
+ raise operationerrfmt(space.w_TypeError,
+ "needs 'void *', got '%s'", w_ctype.name)
+ index = get(space).reserve_next_handle_index()
+ _cdata = rffi.cast(rffi.CCHARP, index + 1)
+ new_cdataobj = cdataobj.W_CDataHandle(space, _cdata, w_ctype, w_x)
+ get(space).store_handle(index, new_cdataobj)
+ return new_cdataobj
+
+ at unwrap_spec(w_cdata=cdataobj.W_CData)
+def from_handle(space, w_cdata):
+ ctype = w_cdata.ctype
+ if (not isinstance(ctype, ctypeptr.W_CTypePtrOrArray) or
+ not ctype.can_cast_anything):
+ raise operationerrfmt(space.w_TypeError,
+ "expected a 'cdata' object with a 'void *' out "
+ "of new_handle(), got '%s'", ctype.name)
+ index = rffi.cast(lltype.Signed, w_cdata._cdata)
+ original_cdataobj = get(space).fetch_handle(index - 1)
+ #
+ if isinstance(original_cdataobj, cdataobj.W_CDataHandle):
+ return original_cdataobj.w_keepalive
+ else:
+ if index == 0:
+ msg = "cannot use from_handle() on NULL pointer"
+ else:
+ msg = "'void *' value does not correspond to any object"
+ raise OperationError(space.w_RuntimeError, space.wrap(msg))
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
@@ -365,8 +365,9 @@
BInt = new_primitive_type("int")
BFloat = new_primitive_type("float")
for i in range(1, 20):
- if (hash(cast(BChar, chr(i))) !=
- hash(cast(BInt, i))):
+ x1 = cast(BChar, chr(i))
+ x2 = cast(BInt, i)
+ if hash(x1) != hash(x2):
break
else:
raise AssertionError("hashes are equal")
@@ -2723,6 +2724,40 @@
assert x.__name__ == '<cdata>'
assert hasattr(x, '__doc__')
+def test_different_types_of_ptr_equality():
+ BVoidP = new_pointer_type(new_void_type())
+ BIntP = new_pointer_type(new_primitive_type("int"))
+ x = cast(BVoidP, 12345)
+ assert x == cast(BIntP, 12345)
+ assert x != cast(BIntP, 12344)
+ assert hash(x) == hash(cast(BIntP, 12345))
+
+def test_new_handle():
+ import _weakref
+ BVoidP = new_pointer_type(new_void_type())
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ class mylist(list):
+ pass
+ o = mylist([2, 3, 4])
+ x = newp_handle(BVoidP, o)
+ assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>"
+ assert x
+ assert from_handle(x) is o
+ assert from_handle(cast(BCharP, x)) is o
+ wr = _weakref.ref(o)
+ del o
+ import gc; gc.collect()
+ assert wr() is not None
+ assert from_handle(x) == list((2, 3, 4))
+ assert from_handle(cast(BCharP, x)) == list((2, 3, 4))
+ del x
+ for i in range(3):
+ if wr() is not None:
+ import gc; gc.collect()
+ assert wr() is None
+ py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
+
+
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.6"
+ assert __version__ == "0.7"
diff --git a/pypy/module/_cffi_backend/test/test_handle.py b/pypy/module/_cffi_backend/test/test_handle.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/test/test_handle.py
@@ -0,0 +1,59 @@
+import random
+from pypy.module._cffi_backend.handle import CffiHandles, reduced_value
+
+
+def test_reduced_value():
+ assert reduced_value(0) == 0
+ assert reduced_value(1) == 0
+ assert reduced_value(2) == 1
+ assert reduced_value(3) == 0
+ assert reduced_value(4) == 2
+ assert reduced_value(5) == 1
+ assert reduced_value(6) == 3
+ assert reduced_value(7) == 0
+ assert reduced_value(8) == 4
+ assert reduced_value(9) == 2
+ assert reduced_value(10) == 5
+ assert reduced_value(11) == 1
+
+
+class PseudoWeakRef(object):
+ _content = 42
+
+ def __call__(self):
+ return self._content
+
+
+def test_cffi_handles_1():
+ ch = CffiHandles(None)
+ expected_content = {}
+ for i in range(10000):
+ index = ch.reserve_next_handle_index()
+ assert 0 <= index < len(ch.handles)
+ assert ch.handles[index]() is None
+ pwr = PseudoWeakRef()
+ expected_content[index] = pwr
+ ch.handles[index] = pwr
+ assert len(ch.handles) < 13500
+ for index, pwr in expected_content.items():
+ assert ch.handles[index] is pwr
+
+def test_cffi_handles_2():
+ ch = CffiHandles(None)
+ expected_content = {}
+ for i in range(10000):
+ index = ch.reserve_next_handle_index()
+ assert 0 <= index < len(ch.handles)
+ assert ch.handles[index]() is None
+ pwr = PseudoWeakRef()
+ expected_content[index] = pwr
+ ch.handles[index] = pwr
+ #
+ if len(expected_content) > 20:
+ r = random.choice(list(expected_content))
+ pwr = expected_content.pop(r)
+ pwr._content = None
+ #
+ assert len(ch.handles) < 100
+ for index, pwr in expected_content.items():
+ assert ch.handles[index] is pwr
diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test_funcptr.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -74,9 +74,9 @@
from _ffi import CDLL, types
# this should return *all* loaded libs, dlopen(NULL)
dll = CDLL(None)
- # Assume CPython, or PyPy compiled with cpyext
- res = dll.getfunc('Py_IsInitialized', [], types.slong)()
- assert res == 1
+ # libm should be loaded
+ res = dll.getfunc('sqrt', [types.double], types.double)(1.0)
+ assert res == 1.0
def test_callfunc(self):
from _ffi import CDLL, types
@@ -139,7 +139,7 @@
def test_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr() { return &dummy; }
DLLEXPORT void set_val_to_ptr(int* ptr, int val) { *ptr = val; }
"""
@@ -158,7 +158,7 @@
def test_convert_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
"""
@@ -170,7 +170,7 @@
def _as_ffi_pointer_(self, ffitype):
assert ffitype is types.void_p
return self.value
-
+
libfoo = CDLL(self.libfoo_name)
get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.void_p)
@@ -259,7 +259,7 @@
def test_typed_pointer_args(self):
"""
- extern int dummy; // defined in test_void_result
+ extern int dummy; // defined in test_void_result
DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
"""
@@ -551,7 +551,7 @@
from _ffi import CDLL, types
libfoo = CDLL(self.libfoo_name)
raises(TypeError, "libfoo.getfunc('sum_xy', [types.void], types.sint)")
-
+
def test_OSError_loading(self):
from _ffi import CDLL, types
raises(OSError, "CDLL('I do not exist')")
@@ -606,7 +606,7 @@
from _rawffi import FUNCFLAG_STDCALL
libm = CDLL(self.libm_name)
pow_addr = libm.getaddressindll('pow')
- wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
+ wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
[types.double, types.double], types.double, FUNCFLAG_STDCALL)
try:
wrong_pow(2, 3) == 8
@@ -622,7 +622,7 @@
from _rawffi import FUNCFLAG_STDCALL
kernel = WinDLL('Kernel32.dll')
sleep_addr = kernel.getaddressindll('Sleep')
- sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
+ sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
types.void, FUNCFLAG_STDCALL)
sleep(10)
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -232,9 +232,9 @@
import _rawffi
# this should return *all* loaded libs, dlopen(NULL)
dll = _rawffi.CDLL(None)
- # Assume CPython, or PyPy compiled with cpyext
- res = dll.ptr('Py_IsInitialized', [], 'l')()
- assert res[0] == 1
+ func = dll.ptr('rand', [], 'i')
+ res = func()
+ assert res[0] != 0
def test_libc_load(self):
import _rawffi
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -6,7 +6,6 @@
borrow_from, make_ref, from_ref)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.objspace.std.setobject import W_SetObject, newset
-from pypy.objspace.std.smalltupleobject import W_SmallTupleObject
PySet_Check, PySet_CheckExact = build_type_checkers("Set")
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
@@ -344,7 +344,7 @@
return
@cpython_api([PyObject, PyObject, PyObject], rffi.INT_real,
- error=-1, external=True) # XXX should not be exported
+ error=-1, external=False)
@func_renamer("cpyext_tp_setattro_%s" % (typedef.name,))
def slot_tp_setattro(space, w_self, w_name, w_value):
if w_value is not None:
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -69,6 +69,7 @@
new_backstrides = [0] * ndims
for nd in range(ndims):
new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
+ assert isinstance(orig_array, W_NDimArray) or orig_array is None
return SliceArray(self.start, new_strides, new_backstrides,
new_shape, self, orig_array)
else:
@@ -356,13 +357,13 @@
self.strides = strides
self.backstrides = backstrides
self.shape = shape
+ if dtype is None:
+ dtype = parent.dtype
if isinstance(parent, SliceArray):
parent = parent.parent # one level only
self.parent = parent
self.storage = parent.storage
self.order = parent.order
- if dtype is None:
- dtype = parent.dtype
self.dtype = dtype
self.size = support.product(shape) * self.dtype.itemtype.get_element_size()
self.start = start
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -2,6 +2,7 @@
from pypy.module.micronumpy.arrayimpl import base
from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
from pypy.module.micronumpy import support
+from pypy.module.micronumpy.interp_boxes import W_GenericBox
from pypy.interpreter.error import OperationError
class ScalarIterator(base.BaseArrayIterator):
@@ -48,6 +49,7 @@
return self.value
def set_scalar_value(self, w_val):
+ assert isinstance(w_val, W_GenericBox)
self.value = w_val.convert_to(self.dtype)
def copy(self, space):
@@ -73,7 +75,7 @@
dtype = self.dtype.float_type or self.dtype
if len(w_arr.get_shape()) > 0:
raise OperationError(space.w_ValueError, space.wrap(
- "could not broadcast input array from shape " +
+ "could not broadcast input array from shape " +
"(%s) into shape ()" % (
','.join([str(x) for x in w_arr.get_shape()],))))
if self.dtype.is_complex_type():
@@ -102,7 +104,7 @@
dtype = self.dtype.float_type
if len(w_arr.get_shape()) > 0:
raise OperationError(space.w_ValueError, space.wrap(
- "could not broadcast input array from shape " +
+ "could not broadcast input array from shape " +
"(%s) into shape ()" % (
','.join([str(x) for x in w_arr.get_shape()],))))
self.value = self.dtype.itemtype.composite(
diff --git a/pypy/module/micronumpy/arrayimpl/sort.py b/pypy/module/micronumpy/arrayimpl/sort.py
--- a/pypy/module/micronumpy/arrayimpl/sort.py
+++ b/pypy/module/micronumpy/arrayimpl/sort.py
@@ -12,7 +12,7 @@
from rpython.rlib.objectmodel import specialize
from pypy.interpreter.error import OperationError
from pypy.module.micronumpy.base import W_NDimArray
-from pypy.module.micronumpy import types
+from pypy.module.micronumpy import interp_dtype, types
from pypy.module.micronumpy.iter import AxisIterator
INT_SIZE = rffi.sizeof(lltype.Signed)
@@ -20,7 +20,7 @@
def make_sort_function(space, itemtype, comp_type, count=1):
TP = itemtype.T
step = rffi.sizeof(TP)
-
+
class Repr(object):
def __init__(self, index_stride_size, stride_size, size, values,
indexes, index_start, start):
@@ -69,13 +69,12 @@
class ArgArrayRepWithStorage(Repr):
def __init__(self, index_stride_size, stride_size, size):
- from pypy.module.micronumpy import interp_dtype
start = 0
dtype = interp_dtype.get_dtype_cache(space).w_longdtype
self.indexes = dtype.itemtype.malloc(size*dtype.get_size())
- self.values = alloc_raw_storage(size * stride_size,
+ self.values = alloc_raw_storage(size * stride_size,
track_allocation=False)
- Repr.__init__(self, index_stride_size, stride_size,
+ Repr.__init__(self, index_stride_size, stride_size,
size, self.values, self.indexes, start, start)
def __del__(self):
@@ -97,7 +96,7 @@
for i in range(stop-start):
retval.setitem(i, lst.getitem(i+start))
return retval
-
+
if count < 2:
def arg_lt(a, b):
# Does numpy do <= ?
@@ -109,14 +108,13 @@
return True
elif a[0][i] > b[0][i]:
return False
- # Does numpy do True?
+ # Does numpy do True?
return False
ArgSort = make_timsort_class(arg_getitem, arg_setitem, arg_length,
arg_getitem_slice, arg_lt)
def argsort(arr, space, w_axis, itemsize):
- from pypy.module.micronumpy import interp_dtype
if w_axis is space.w_None:
# note that it's fine ot pass None here as we're not going
# to pass the result around (None is the link to base in slices)
@@ -182,7 +180,7 @@
class SortCache(object):
built = False
-
+
def __init__(self, space):
if self.built:
return
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -27,10 +27,10 @@
from pypy.module.micronumpy.arrayimpl import concrete, scalar
if not shape:
- impl = scalar.Scalar(dtype)
+ impl = scalar.Scalar(dtype.base)
else:
- strides, backstrides = calc_strides(shape, dtype, order)
- impl = concrete.ConcreteArray(shape, dtype, order, strides,
+ strides, backstrides = calc_strides(shape, dtype.base, order)
+ impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
backstrides)
return W_NDimArray(impl)
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -14,6 +14,7 @@
from pypy.module.micronumpy.interp_arrayops import where
from pypy.module.micronumpy import interp_ufuncs
from rpython.rlib.objectmodel import specialize, instantiate
+from rpython.rlib.nonconst import NonConstant
class BogusBytecode(Exception):
@@ -40,6 +41,10 @@
TWO_ARG_FUNCTIONS = ["dot", 'take']
THREE_ARG_FUNCTIONS = ['where']
+class W_TypeObject(W_Root):
+ def __init__(self, name):
+ self.name = name
+
class FakeSpace(object):
w_ValueError = "ValueError"
w_TypeError = "TypeError"
@@ -48,17 +53,17 @@
w_NotImplementedError = "NotImplementedError"
w_None = None
- w_bool = "bool"
- w_int = "int"
- w_float = "float"
- w_list = "list"
- w_long = "long"
- w_tuple = 'tuple'
- w_slice = "slice"
- w_str = "str"
- w_unicode = "unicode"
- w_complex = "complex"
- w_dict = "dict"
+ w_bool = W_TypeObject("bool")
+ w_int = W_TypeObject("int")
+ w_float = W_TypeObject("float")
+ w_list = W_TypeObject("list")
+ w_long = W_TypeObject("long")
+ w_tuple = W_TypeObject('tuple')
+ w_slice = W_TypeObject("slice")
+ w_str = W_TypeObject("str")
+ w_unicode = W_TypeObject("unicode")
+ w_complex = W_TypeObject("complex")
+ w_dict = W_TypeObject("dict")
def __init__(self):
"""NOT_RPYTHON"""
@@ -73,6 +78,13 @@
def issequence_w(self, w_obj):
return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
+ def len(self, w_obj):
+ assert isinstance(w_obj, ListObject)
+ return self.wrap(len(w_obj.items))
+
+ def getattr(self, w_obj, w_attr):
+ return StringObject(NonConstant('foo'))
+
def isinstance_w(self, w_obj, w_tp):
return w_obj.tp == w_tp
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -268,14 +268,30 @@
class W_VoidBox(W_FlexibleBox):
- @unwrap_spec(item=str)
- def descr_getitem(self, space, item):
+ def descr_getitem(self, space, w_item):
+ from pypy.module.micronumpy.types import VoidType
+ if space.isinstance_w(w_item, space.w_str):
+ item = space.str_w(w_item)
+ elif space.isinstance_w(w_item, space.w_int):
+ #Called by iterator protocol
+ indx = space.int_w(w_item)
+ try:
+ item = self.dtype.fieldnames[indx]
+ except IndexError:
+ raise OperationError(space.w_IndexError,
+ space.wrap("Iterated over too many fields %d" % indx))
+ else:
+ raise OperationError(space.w_IndexError, space.wrap(
+ "Can only access fields of record with int or str"))
try:
ofs, dtype = self.dtype.fields[item]
except KeyError:
raise OperationError(space.w_IndexError,
space.wrap("Field %s does not exist" % item))
- read_val = dtype.itemtype.read(self.arr, self.ofs, ofs, dtype)
+ if isinstance(dtype.itemtype, VoidType):
+ read_val = dtype.itemtype.readarray(self.arr, self.ofs, ofs, dtype)
+ else:
+ read_val = dtype.itemtype.read(self.arr, self.ofs, ofs, dtype)
if isinstance (read_val, W_StringBox):
# StringType returns a str
return space.wrap(dtype.itemtype.to_str(read_val))
@@ -373,7 +389,7 @@
W_LongDoubleBox = W_Float64Box
W_CLongDoubleBox = W_Complex64Box
-
+
W_GenericBox.typedef = TypeDef("generic",
__module__ = "numpypy",
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -65,6 +65,10 @@
self.float_type = None
self.shape = list(shape)
self.subdtype = subdtype
+ if not subdtype:
+ self.base = self
+ else:
+ self.base = subdtype.base
@specialize.argtype(1)
def box(self, value):
@@ -80,7 +84,8 @@
return self.itemtype.coerce(space, self, w_item)
def getitem(self, arr, i):
- return self.itemtype.read(arr, i, 0)
+ item = self.itemtype.read(arr, i, 0)
+ return item
def getitem_bool(self, arr, i):
return self.itemtype.read_bool(arr, i, 0)
@@ -113,6 +118,9 @@
def descr_get_alignment(self, space):
return space.wrap(self.itemtype.alignment)
+ def descr_get_base(self, space):
+ return space.wrap(self.base)
+
def descr_get_subdtype(self, space):
return space.newtuple([space.wrap(self.subdtype), self.descr_get_shape(space)])
@@ -423,6 +431,7 @@
fields = GetSetProperty(W_Dtype.descr_get_fields),
names = GetSetProperty(W_Dtype.descr_get_names),
subdtype = GetSetProperty(W_Dtype.descr_get_subdtype),
+ base = GetSetProperty(W_Dtype.descr_get_base),
)
W_Dtype.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -21,7 +21,7 @@
from rpython.rlib.rstring import StringBuilder
from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
-def _find_shape(space, w_size):
+def _find_shape(space, w_size, dtype):
if space.is_none(w_size):
return []
if space.isinstance_w(w_size, space.w_int):
@@ -29,6 +29,7 @@
shape = []
for w_item in space.fixedview(w_size):
shape.append(space.int_w(w_item))
+ shape += dtype.shape
return shape[:]
class __extend__(W_NDimArray):
@@ -829,7 +830,7 @@
space.wrap("unsupported param"))
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype)
return W_NDimArray.from_shape(shape, dtype)
@@ -842,10 +843,10 @@
"""
from rpython.rtyper.lltypesystem import rffi
from rpython.rlib.rawstorage import RAW_STORAGE_PTR
- shape = _find_shape(space, w_shape)
storage = rffi.cast(RAW_STORAGE_PTR, addr)
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
+ shape = _find_shape(space, w_shape, dtype)
return W_NDimArray.from_shape_and_storage(shape, storage, dtype)
W_NDimArray.typedef = TypeDef(
@@ -1029,7 +1030,7 @@
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
return space.wrap(W_NDimArray.from_shape(shape, dtype=dtype, order=order))
@@ -1039,7 +1040,7 @@
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
arr = W_NDimArray.from_shape(shape, dtype=dtype, order=order)
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -32,13 +32,13 @@
shape dimension
which is back 25 and forward 1,
which is x.strides[1] * (x.shape[1] - 1) + x.strides[0]
-so if we precalculate the overflow backstride as
+so if we precalculate the overflow backstride as
[x.strides[i] * (x.shape[i] - 1) for i in range(len(x.shape))]
we can go faster.
All the calculations happen in next()
next_skip_x() tries to do the iteration for a number of steps at once,
-but then we cannot gaurentee that we only overflow one single shape
+but then we cannot gaurentee that we only overflow one single shape
dimension, perhaps we could overflow times in one big step.
"""
@@ -170,7 +170,8 @@
self.dtype.setitem(self.array, self.offset, elem)
def getitem(self):
- return self.dtype.getitem(self.array, self.offset)
+ item = self.dtype.getitem(self.array, self.offset)
+ return item
def getitem_bool(self):
return self.dtype.getitem_bool(self.array, self.offset)
@@ -288,12 +289,13 @@
self.dim = dim
self.array = array
self.dtype = array.dtype
-
+
def setitem(self, elem):
self.dtype.setitem(self.array, self.offset, elem)
def getitem(self):
- return self.dtype.getitem(self.array, self.offset)
+ item = self.dtype.getitem(self.array, self.offset)
+ return item
@jit.unroll_safe
def next(self):
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -275,7 +275,10 @@
from numpypy import array, dtype
from cPickle import loads, dumps
a = array([1,2,3])
- assert a.dtype.__reduce__() == (dtype, ('i8', 0, 1), (3, '<', None, None, None, -1, -1, 0))
+ if self.ptr_size == 8:
+ assert a.dtype.__reduce__() == (dtype, ('i8', 0, 1), (3, '<', None, None, None, -1, -1, 0))
+ else:
+ assert a.dtype.__reduce__() == (dtype, ('i4', 0, 1), (3, '<', None, None, None, -1, -1, 0))
assert loads(dumps(a.dtype)) == a.dtype
class AppTestTypes(BaseAppTestDtypes):
@@ -768,6 +771,7 @@
assert d.num == 20
assert d.itemsize == 20
assert d.kind == 'V'
+ assert d.base == d
assert d.type is void
assert d.char == 'V'
assert d.names == ("x", "y", "z", "value")
@@ -798,7 +802,8 @@
assert dt.shape == (10,)
assert dt.kind == 'V'
assert dt.fields == None
- assert dt.subdtype == (dtype("float64"), (10,))
+ assert dt.subdtype == (dtype(float), (10,))
+ assert dt.base == dtype(float)
def test_pickle_record(self):
from numpypy import array, dtype
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -18,10 +18,12 @@
def get_element_size():
return 1
+ def __init__(self):
+ self.base = self
+
def get_size(self):
return 1
-
def create_slice(a, chunks):
return Chunks(chunks).apply(W_NDimArray(a)).implementation
@@ -2700,7 +2702,7 @@
assert a[1]['y'] == 1
def test_subarrays(self):
- from numpypy import dtype, array
+ from numpypy import dtype, array, zeros
d = dtype([("x", "int", 3), ("y", "float", 5)])
a = array([([1, 2, 3], [0.5, 1.5, 2.5, 3.5, 4.5]), ([4, 5, 6], [5.5, 6.5, 7.5, 8.5, 9.5])], dtype=d)
@@ -2713,6 +2715,42 @@
a[0]["x"][0] = 200
assert a[0]["x"][0] == 200
+ d = dtype([("x", "int", (2, 3))])
+ a = array([([[1, 2, 3], [4, 5, 6]],)], dtype=d)
+
+ assert a[0]["x"].dtype == dtype("int64")
+ assert a[0]["x"][0].dtype == dtype("int64")
+
+ assert (a[0]["x"][0] == [1, 2, 3]).all()
+ assert (a[0]["x"] == [[1, 2, 3], [4, 5, 6]]).all()
+
+ d = dtype((float, (10, 10)))
+ a = zeros((3,3), dtype=d)
+ assert a[0, 0].shape == (10, 10)
+ assert a.shape == (3, 3, 10, 10)
+ a[0, 0] = 500
+ assert (a[0, 0, 0] == 500).all()
+ assert a[0, 0, 0].shape == (10,)
+
+ def test_multidim_subarray(self):
+ from numpypy import dtype, array
+
+ d = dtype([("x", "int", (2, 3))])
+ a = array([([[1, 2, 3], [4, 5, 6]],)], dtype=d)
+
+ assert a[0]["x"].dtype == dtype("int64")
+ assert a[0]["x"][0].dtype == dtype("int64")
+
+ assert (a[0]["x"][0] == [1, 2, 3]).all()
+ assert (a[0]["x"] == [[1, 2, 3], [4, 5, 6]]).all()
+
+ def test_list_record(self):
+ from numpypy import dtype, array
+
+ d = dtype([("x", "int", 3), ("y", "float", 5)])
+ a = array([([1, 2, 3], [0.5, 1.5, 2.5, 3.5, 4.5]), ([4, 5, 6], [5.5, 6.5, 7.5, 8.5, 9.5])], dtype=d)
+
+ assert len(list(a[0])) == 2
class AppTestPyPy(BaseNumpyAppTest):
def setup_class(cls):
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -1686,6 +1686,7 @@
return space.wrap(self.to_str(box))
def build_and_convert(self, space, mydtype, box):
+ assert isinstance(box, interp_boxes.W_GenericBox)
if box.get_dtype(space).is_str_or_unicode():
arg = box.get_dtype(space).itemtype.to_str(box)
else:
@@ -1702,16 +1703,47 @@
class VoidType(BaseType, BaseStringType):
T = lltype.Char
- def coerce(self, space, dtype, w_items):
+ def _coerce(self, space, arr, ofs, dtype, w_items, shape):
items_w = space.fixedview(w_items)
- arr = VoidBoxStorage(self.size, dtype)
- ofs = 0
for i in range(len(items_w)):
subdtype = dtype.subdtype
itemtype = subdtype.itemtype
- w_box = itemtype.coerce(space, dtype.subdtype, items_w[i])
- itemtype.store(arr, 0, ofs, w_box)
- ofs += itemtype.get_element_size()
+ if space.len_w(shape) <= 1:
+ w_box = itemtype.coerce(space, dtype.subdtype, items_w[i])
+ itemtype.store(arr, 0, ofs, w_box)
+ ofs += itemtype.get_element_size()
+ else:
+ size = 1
+ for dimension in shape[1:]:
+ size *= dimension
+ size *= itemtype.get_element_size()
+ for w_item in items_w:
+ self._coerce(space, arr, ofs, dtype, w_items, shape[1:])
+ ofs += size
+ return arr
+
+ def _coerce(self, space, arr, ofs, dtype, w_items, shape):
+ # TODO: Make sure the shape and the array match
+ items_w = space.fixedview(w_items)
+ subdtype = dtype.subdtype
+ itemtype = subdtype.itemtype
+ if len(shape) <= 1:
+ for i in range(len(items_w)):
+ w_box = itemtype.coerce(space, dtype.subdtype, items_w[i])
+ itemtype.store(arr, 0, ofs, w_box)
+ ofs += itemtype.get_element_size()
+ else:
+ for w_item in items_w:
+ size = 1
+ for dimension in shape[1:]:
+ size *= dimension
+ size *= itemtype.get_element_size()
+ self._coerce(space, arr, ofs, dtype, w_item, shape[1:])
+ ofs += size
+
+ def coerce(self, space, dtype, w_items):
+ arr = VoidBoxStorage(self.size, dtype)
+ self._coerce(space, arr, 0, dtype, w_items, dtype.shape)
return interp_boxes.W_VoidBox(arr, 0, dtype)
@jit.unroll_safe
@@ -1720,12 +1752,13 @@
for k in range(self.get_element_size()):
arr.storage[k + ofs] = box.arr.storage[k + box.ofs]
- def read(self, arr, i, offset, dtype=None):
+ def readarray(self, arr, i, offset, dtype=None):
from pypy.module.micronumpy.base import W_NDimArray
if dtype is None:
dtype = arr.dtype
strides, backstrides = support.calc_strides(dtype.shape, dtype.subdtype, arr.order)
- implementation = SliceArray(i + offset, strides, backstrides, dtype.shape, arr, arr, dtype.subdtype)
+ implementation = SliceArray(i + offset, strides, backstrides,
+ dtype.shape, arr, W_NDimArray(arr), dtype.subdtype)
return W_NDimArray(implementation)
NonNativeVoidType = VoidType
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -75,16 +75,19 @@
cache.w_optimize_hook = w_hook
cache.in_recursion = NonConstant(False)
+
def set_abort_hook(space, w_hook):
""" set_abort_hook(hook)
Set a hook (callable) that will be called each time there is tracing
aborted due to some reason.
- The hook will be called as in: hook(jitdriver_name, greenkey, reason)
+ The hook will be called with the signature:
+
+ hook(jitdriver_name, greenkey, reason, operations)
Reason is a string, the meaning of other arguments is the same
- as attributes on JitLoopInfo object
+ as attributes on JitLoopInfo object.
"""
cache = space.fromcache(Cache)
cache.w_abort_hook = w_hook
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -1,26 +1,29 @@
from rpython.jit.codewriter.policy import JitPolicy
+from rpython.rlib import jit_hooks
from rpython.rlib.jit import JitHookInterface, Counters
-from rpython.rlib import jit_hooks
+
from pypy.interpreter.error import OperationError
-from pypy.module.pypyjit.interp_resop import Cache, wrap_greenkey,\
- WrappedOp, W_JitLoopInfo
+from pypy.module.pypyjit.interp_resop import (Cache, wrap_greenkey,
+ WrappedOp, W_JitLoopInfo, wrap_oplist)
+
class PyPyJitIface(JitHookInterface):
- def on_abort(self, reason, jitdriver, greenkey, greenkey_repr):
+ def on_abort(self, reason, jitdriver, greenkey, greenkey_repr, logops, operations):
space = self.space
cache = space.fromcache(Cache)
if cache.in_recursion:
return
if space.is_true(cache.w_abort_hook):
cache.in_recursion = True
+ oplist_w = wrap_oplist(space, logops, operations)
try:
try:
space.call_function(cache.w_abort_hook,
- space.wrap(jitdriver.name),
- wrap_greenkey(space, jitdriver,
- greenkey, greenkey_repr),
- space.wrap(
- Counters.counter_names[reason]))
+ space.wrap(jitdriver.name),
+ wrap_greenkey(space, jitdriver, greenkey, greenkey_repr),
+ space.wrap(Counters.counter_names[reason]),
+ space.newlist(oplist_w)
+ )
except OperationError, e:
e.write_unraisable(space, "jit hook ", cache.w_abort_hook)
finally:
diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py
--- a/pypy/module/pypyjit/test/test_jit_hook.py
+++ b/pypy/module/pypyjit/test/test_jit_hook.py
@@ -16,6 +16,7 @@
from rpython.jit.metainterp.typesystem import llhelper
from rpython.rlib.jit import JitDebugInfo, AsmInfo, Counters
+
class MockJitDriverSD(object):
class warmstate(object):
@staticmethod
@@ -34,8 +35,10 @@
jitdrivers_sd = [MockJitDriverSD]
+
class AppTestJitHook(object):
spaceconfig = dict(usemodules=('pypyjit',))
+
def setup_class(cls):
if cls.runappdirect:
py.test.skip("Can't run this test with -A")
@@ -86,7 +89,7 @@
def interp_on_abort():
pypy_hooks.on_abort(Counters.ABORT_TOO_LONG, pypyjitdriver,
- greenkey, 'blah')
+ greenkey, 'blah', Logger(MockSD), [])
space = cls.space
cls.w_on_compile = space.wrap(interp2app(interp_on_compile))
@@ -189,12 +192,12 @@
import pypyjit
l = []
- def hook(jitdriver_name, greenkey, reason):
- l.append((jitdriver_name, reason))
+ def hook(jitdriver_name, greenkey, reason, operations):
+ l.append((jitdriver_name, reason, operations))
pypyjit.set_abort_hook(hook)
self.on_abort()
- assert l == [('pypyjit', 'ABORT_TOO_LONG')]
+ assert l == [('pypyjit', 'ABORT_TOO_LONG', [])]
def test_on_optimize(self):
import pypyjit
diff --git a/pypy/module/pypyjit/test_pypy_c/bug1.py b/pypy/module/pypyjit/test_pypy_c/bug1.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/bug1.py
@@ -0,0 +1,57 @@
+import cffi, thread, time, sys
+
+
+ffi = cffi.FFI()
+
+ffi.cdef("""
+ long foobar(long a, long b, long c, long d, long e, long f,
+ long a2, long b2, long c2, long d2, long e2, long f2,
+ long a3, long b3, long c3, long d3, long e3, long f3,
+ long a4, long b4, long c4, long d4, long e4, long f4);
+""")
+
+lib = ffi.verify("""
+ long foobar(long a, long b, long c, long d, long e, long f,
+ long a2, long b2, long c2, long d2, long e2, long f2,
+ long a3, long b3, long c3, long d3, long e3, long f3,
+ long a4, long b4, long c4, long d4, long e4, long f4)
+ {
+ return a * 1 + b * 2 + c * 3 + d * 4 + e * 5 + f * 6 +
+ (a2 * 1 + b2 * 2 + c2 * 3 + d2 * 4 + e2 * 5 + f2 * 6) * (-3) +
+ (a3 * 1 + b3 * 2 + c3 * 3 + d3 * 4 + e3 * 5 + f3 * 6) * (-5) +
+ (a4 * 1 + b4 * 2 + c4 * 3 + d4 * 4 + e4 * 5 + f4 * 6) * (-7);
+ }
+""")
+
+
+def runme():
+ for j in range(10):
+ for i in range(10000):
+ args = [i-k for k in range(24)]
+ x = lib.foobar(*args)
+ (a,b,c,d,e,f,a2,b2,c2,d2,e2,f2,
+ a3,b3,c3,d3,e3,f3,a4,b4,c4,d4,e4,f4) = args
+ assert x == (
+ a * 1 + b * 2 + c * 3 + d * 4 + e * 5 + f * 6 +
+ (a2 * 1 + b2 * 2 + c2 * 3 + d2 * 4 + e2 * 5 + f2 * 6) * (-3) +
+ (a3 * 1 + b3 * 2 + c3 * 3 + d3 * 4 + e3 * 5 + f3 * 6) * (-5) +
+ (a4 * 1 + b4 * 2 + c4 * 3 + d4 * 4 + e4 * 5 + f4 * 6) * (-7))
+
+done = []
+
+def submain():
+ try:
+ runme()
+ err = None
+ except:
+ err = sys.exc_info()
+ done.append(err)
+
+for i in range(2):
+ thread.start_new_thread(submain, ())
+while len(done) < 2:
+ time.sleep(0.1)
+
+for err in done:
+ if err is not None:
+ raise err[0], err[1], err[2]
diff --git a/pypy/module/pypyjit/test_pypy_c/test_array.py b/pypy/module/pypyjit/test_pypy_c/test_array.py
--- a/pypy/module/pypyjit/test_pypy_c/test_array.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_array.py
@@ -105,6 +105,7 @@
assert loop.match("""
i10 = int_lt(i6, 1000)
guard_true(i10, descr=...)
+ guard_not_invalidated(descr=...)
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
f13 = getarrayitem_raw(i8, i6, descr=<ArrayF 8>)
@@ -141,6 +142,7 @@
assert loop.match("""
i10 = int_lt(i6, 1000)
guard_true(i10, descr=...)
+ guard_not_invalidated(descr=...)
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
i13 = getarrayitem_raw(i8, i6, descr=<Array. 4>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_bug.py b/pypy/module/pypyjit/test_pypy_c/test_bug.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_bug.py
@@ -0,0 +1,14 @@
+import os, sys, py, subprocess
+
+localdir = os.path.dirname(os.path.abspath(__file__))
+
+
+def test_bug1():
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux-only test")
+
+ cmdline = ['taskset', '-c', '0',
+ sys.executable, os.path.join(localdir, 'bug1.py')]
+ popen = subprocess.Popen(cmdline)
+ err = popen.wait()
+ assert err == 0
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -487,6 +487,7 @@
assert loop.match("""
i2 = int_lt(i0, i1)
guard_true(i2, descr=...)
+ guard_not_invalidated(descr=...)
i3 = force_token()
i4 = int_add(i0, 1)
--TICK--
@@ -586,7 +587,6 @@
""", [1000])
loop, = log.loops_by_id('call')
assert loop.match_by_id('call', '''
- guard_not_invalidated(descr=<.*>)
i1 = force_token()
''')
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -44,6 +44,7 @@
# gc_id call is hoisted out of the loop, the id of a value obviously
# can't change ;)
assert loop.match_by_id("getitem", """
+ ...
i26 = call(ConstClass(ll_dict_lookup), p18, p6, i25, descr=...)
...
p33 = getinteriorfield_gc(p31, i26, descr=<InteriorFieldDescr <FieldP dictentry.value .*>>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py
--- a/pypy/module/pypyjit/test_pypy_c/test_misc.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py
@@ -36,7 +36,7 @@
assert loop0.match(expected)
# XXX: The retracing fails to form a loop since j
More information about the pypy-commit
mailing list