Author: Ronny Pfannschmidt <[email protected]>
Branch: pytest
Changeset: r60450:3395bce3ab2b
Date: 2013-01-25 13:36 +0100
http://bitbucket.org/pypy/pypy/changeset/3395bce3ab2b/
Log: merge from default
diff --git a/lib-python/2.7/test/test_iterlen.py
b/lib-python/2.7/test/test_iterlen.py
--- a/lib-python/2.7/test/test_iterlen.py
+++ b/lib-python/2.7/test/test_iterlen.py
@@ -94,7 +94,11 @@
def test_no_len_for_infinite_repeat(self):
# The repeat() object can also be infinite
- self.assertRaises(TypeError, len, repeat(None))
+ if test_support.check_impl_detail(pypy=True):
+ # 3.4 (PEP 424) behavior
+ self.assertEqual(len(repeat(None)), NotImplemented)
+ else:
+ self.assertRaises(TypeError, len, repeat(None))
class TestXrange(TestInvariantWithoutMutations):
@@ -230,6 +234,7 @@
self.assertRaises(RuntimeError, b.extend, BadLen())
self.assertRaises(RuntimeError, b.extend, BadLengthHint())
+ @test_support.impl_detail("PEP 424 disallows None results", pypy=False)
def test_invalid_hint(self):
# Make sure an invalid result doesn't muck-up the works
self.assertEqual(list(NoneLengthHint()), list(range(10)))
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -17,8 +17,8 @@
from pypy.conftest import option as pypy_option
from pypy.tool.pytest import appsupport
-from pypy.tool.pytest.confpath import pypydir, testdir, testresultdir
-from pypy.config.parse import parse_info
+from pypy.tool.pytest.confpath import pypydir, rpythondir, testdir,
testresultdir
+from rpython.config.parse import parse_info
pytest_plugins = "resultlog",
rsyncdirs = ['.', '../pypy/']
@@ -40,7 +40,7 @@
dest="unittest_filter", help="Similar to -k, XXX")
def gettimeout(timeout):
- from test import pystone
+ from rpython.translator.test import rpystone
if timeout.endswith('mp'):
megapystone = float(timeout[:-2])
t, stone = pystone.Proc0(10000)
@@ -281,7 +281,7 @@
RegrTest('test_ioctl.py'),
RegrTest('test_isinstance.py', core=True),
RegrTest('test_iter.py', core=True),
- RegrTest('test_iterlen.py', skip="undocumented internal API behavior
__length_hint__"),
+ RegrTest('test_iterlen.py', core=True, usemodules="_collections
itertools"),
RegrTest('test_itertools.py', core=True, usemodules="itertools struct"),
RegrTest('test_json.py'),
RegrTest('test_kqueue.py'),
@@ -584,7 +584,7 @@
watchdog_name = 'watchdog_nt.py'
else:
watchdog_name = 'watchdog.py'
- watchdog_script = pypydir.join('tool', watchdog_name)
+ watchdog_script = rpythondir.join('tool', watchdog_name)
regr_script = pypydir.join('tool', 'pytest',
'run-script', 'regrverbose.py')
diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst
--- a/pypy/doc/arm.rst
+++ b/pypy/doc/arm.rst
@@ -130,15 +130,7 @@
export SB2=/srv/chroot/precise_arm
export SB2OPT='-t ARM'
-Once this is set, you can call the translator
-
-::
-
- pypy ~/path_to_pypy_checkout/pypy/translator/goal/translate.py -O1
--platform=arm target.py
-
-If everything worked correctly this should yield an ARM binary. Running this
binary in the ARM chroot or on an ARM device should produce the output ``"Hello
World"``.
-
-.. _`this`:
+Once this is set, you can call the translator. For example save this file
::
@@ -148,3 +140,22 @@
def target(*args):
return main, None
+
+and call the translator
+
+::
+
+ pypy ~/path_to_pypy_checkout/pypy/translator/goal/translate.py -O1
--platform=arm target.py
+
+If everything worked correctly this should yield an ARM binary. Running this
binary in the ARM chroot or on an ARM device should produce the output ``"Hello
World"``.
+
+To translate the full python pypy interpreter with a jit, you can cd into
pypy/goal and call
+
+::
+
+ pypy <path to rpython>/rpython/translator/goal/translate.py -Ojit
--platform=arm --gcrootfinder=shadowstack --jit-backend=arm
targetpypystandalone.py
+
+The gcrootfinder option is needed to work around `issue 1377`_ and the
jit-backend works around `issue 1376`_
+
+.. _`issue 1377`: https://bugs.pypy.org/issue1377
+.. _`issue 1376`: https://bugs.pypy.org/issue1376
diff --git a/pypy/doc/getting-started-python.rst
b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -86,8 +86,8 @@
4. Run::
- cd pypy/translator/goal
- python translate.py --opt=jit targetpypystandalone.py
+ cd pypy/goal
+ python ../../rpython/bin/rpython --opt=jit targetpypystandalone.py
possibly replacing ``--opt=jit`` with another `optimization level`_
of your choice like ``--opt=2`` if you do not want to include the JIT
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,9 @@
.. this is a revision shortly after release-2.0-beta1
.. startrev: 0e6161a009c6
+.. branch: split-rpython
+Split rpython and pypy into seperate directories
+
.. branch: callback-jit
Callbacks from C are now better JITted
@@ -40,3 +43,7 @@
.. branch: fix-lookinside-iff-oopspec
Fixed the interaction between two internal tools for controlling the JIT.
+
+.. branch: inline-virtualref-2
+Better optimized certain types of frame accesses in the JIT, particularly
+around exceptions that escape the function they were raised in.
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
@@ -521,7 +521,11 @@
return self.space.wrap(self.counter)
def next(self):
- self.deque.checklock(self.lock)
+ if self.lock is not self.deque.lock:
+ self.counter = 0
+ raise OperationError(
+ self.space.w_RuntimeError,
+ self.space.wrap("deque mutated during iteration"))
if self.counter == 0:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
self.counter -= 1
@@ -560,7 +564,11 @@
return self.space.wrap(self.counter)
def next(self):
- self.deque.checklock(self.lock)
+ if self.lock is not self.deque.lock:
+ self.counter = 0
+ raise OperationError(
+ self.space.w_RuntimeError,
+ self.space.wrap("deque mutated during iteration"))
if self.counter == 0:
raise OperationError(self.space.w_StopIteration, self.space.w_None)
self.counter -= 1
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py
b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -26,3 +26,25 @@
--THREAD-TICK--
jump(..., descr=...)
""")
+
+ def test_tls(self):
+ def main(n):
+ import thread
+ local = thread._local()
+ local.x = 1
+ i = 0
+ while i < n:
+ i += local.x
+ return 0
+ log = self.run(main, [500])
+ assert round(log.result, 6) == round(main(500), 6)
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i53 = int_lt(i48, i27)
+ guard_true(i53, descr=...)
+ i54 = int_add_ovf(i48, i47)
+ guard_no_overflow(descr=...)
+ --TICK--
+ i58 = arraylen_gc(p43, descr=...)
+ jump(p0, p1, p3, p5, p10, p12, p14, i54, i27, i47, p45, p43,
descr=...)
+ """)
diff --git a/pypy/module/rctime/interp_time.py
b/pypy/module/rctime/interp_time.py
--- a/pypy/module/rctime/interp_time.py
+++ b/pypy/module/rctime/interp_time.py
@@ -448,7 +448,9 @@
raise OperationError(space.w_ValueError,
space.wrap("year out of range"))
- if rffi.getintfield(glob_buf, 'c_tm_wday') < 0:
+ # tm_wday does not need checking of its upper-bound since taking "%
+ # 7" in gettmarg() automatically restricts the range.
+ if rffi.getintfield(glob_buf, 'c_tm_wday') < -1:
raise OperationError(space.w_ValueError,
space.wrap("day of week out of range"))
diff --git a/pypy/module/rctime/test/test_rctime.py
b/pypy/module/rctime/test/test_rctime.py
--- a/pypy/module/rctime/test/test_rctime.py
+++ b/pypy/module/rctime/test/test_rctime.py
@@ -113,6 +113,9 @@
if os.name != 'nt':
assert rctime.mktime(rctime.localtime(-1)) == -1
+ res = rctime.mktime((2000, 1, 1, 0, 0, 0, -1, -1, -1))
+ assert rctime.ctime(res) == 'Sat Jan 1 00:00:00 2000'
+
def test_asctime(self):
import time as rctime
rctime.asctime()
diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -30,6 +30,9 @@
w_dict = space.newdict(instance=True)
self.dicts[ec] = w_dict
self._register_in_ec(ec)
+ # cache the last seen dict, works because we are protected by the GIL
+ self.last_dict = w_dict
+ self.last_ec = ec
def _register_in_ec(self, ec):
if not ec.space.config.translation.rweakref:
@@ -60,10 +63,14 @@
def getdict(self, space):
ec = space.getexecutioncontext()
+ if ec is self.last_ec:
+ return self.last_dict
try:
w_dict = self.dicts[ec]
except KeyError:
w_dict = self.create_new_dict(ec)
+ self.last_ec = ec
+ self.last_dict = w_dict
return w_dict
def descr_local__new__(space, w_subtype, __args__):
@@ -91,3 +98,5 @@
local = wref()
if local is not None:
del local.dicts[ec]
+ local.last_dict = None
+ local.last_ec = None
diff --git a/pypy/module/thread/test/test_local.py
b/pypy/module/thread/test/test_local.py
--- a/pypy/module/thread/test/test_local.py
+++ b/pypy/module/thread/test/test_local.py
@@ -108,3 +108,54 @@
gc.collect()
assert done == ['ok', 'del']
done.append('shutdown')
+
+def test_local_caching():
+ from pypy.module.thread.os_local import Local
+ class FakeSpace:
+ def getexecutioncontext(self):
+ return self.ec
+
+ def getattr(*args):
+ pass
+ def call_obj_args(*args):
+ pass
+ def newdict(*args, **kwargs):
+ return {}
+ def wrap(self, obj):
+ return obj
+ def type(self, obj):
+ return type(obj)
+ class config:
+ class translation:
+ rweakref = True
+
+ class FakeEC:
+ def __init__(self, space):
+ self.space = space
+ self._thread_local_objs = None
+ space = FakeSpace()
+ ec1 = FakeEC(space)
+ space.ec = ec1
+
+ l = Local(space, None)
+ assert l.last_dict is l.dicts[ec1]
+ assert l.last_ec is ec1
+ d1 = l.getdict(space)
+ assert d1 is l.last_dict
+
+ ec2 = space.ec = FakeEC(space)
+ d2 = l.getdict(space)
+ assert l.last_dict is d2
+ assert d2 is l.dicts[ec2]
+ assert l.last_ec is ec2
+ dicts = l.dicts
+ l.dicts = "nope"
+ assert l.getdict(space) is d2
+ l.dicts = dicts
+
+ space.ec = ec1
+ assert l.getdict(space) is d1
+ l.dicts = "nope"
+ assert l.getdict(space) is d1
+ l.dicts = dicts
+
diff --git a/pypy/module/unicodedata/test/test_unicodedata.py
b/pypy/module/unicodedata/test/test_unicodedata.py
--- a/pypy/module/unicodedata/test/test_unicodedata.py
+++ b/pypy/module/unicodedata/test/test_unicodedata.py
@@ -82,8 +82,7 @@
import unicodedata
raises(TypeError, unicodedata.normalize, 'x')
- @py.test.mark.skipif("sys.maxunicode < 0x10ffff",
- reason="requires a 'wide' python build.")
+ @py.test.mark.skipif("sys.maxunicode < 0x10ffff")
def test_normalize_wide(self):
import unicodedata
assert unicodedata.normalize('NFC', u'\U000110a5\U000110ba') ==
u'\U000110ab'
diff --git a/pypy/objspace/std/bytearraytype.py
b/pypy/objspace/std/bytearraytype.py
--- a/pypy/objspace/std/bytearraytype.py
+++ b/pypy/objspace/std/bytearraytype.py
@@ -15,6 +15,7 @@
str_splitlines, str_translate)
from pypy.objspace.std.listtype import (
list_append, list_extend)
+from rpython.rlib.objectmodel import newlist_hint, resizelist_hint
bytearray_insert = SMM('insert', 3,
@@ -87,8 +88,10 @@
return [c for c in string]
# sequence of bytes
- data = []
w_iter = space.iter(w_source)
+ length_hint = space.length_hint(w_source, 0)
+ data = newlist_hint(length_hint)
+ extended = 0
while True:
try:
w_item = space.next(w_iter)
@@ -98,6 +101,9 @@
break
value = getbytevalue(space, w_item)
data.append(value)
+ extended += 1
+ if extended < length_hint:
+ resizelist_hint(data, extended)
return data
def descr_bytearray__reduce__(space, w_self):
diff --git a/pypy/objspace/std/dictmultiobject.py
b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -54,6 +54,9 @@
# every module needs its own strategy, because the strategy stores
# the version tag
strategy = ModuleDictStrategy(space)
+ elif space.config.objspace.std.withmapdict and instance:
+ from pypy.objspace.std.mapdict import MapDictStrategy
+ strategy = space.fromcache(MapDictStrategy)
elif instance or strdict or module:
assert w_type is None
@@ -349,7 +352,7 @@
self.pos = 0
def length(self):
- if self.dictimplementation is not None:
+ if self.dictimplementation is not None and self.len != -1:
return self.len - self.pos
return 0
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -593,6 +593,9 @@
# ____________________________________________________________
# dict implementation
+def get_terminator_for_dicts(space):
+ return DictTerminator(space, None)
+
class MapDictStrategy(DictStrategy):
erase, unerase = rerased.new_erasing_pair("map")
@@ -602,13 +605,19 @@
def __init__(self, space):
self.space = space
+ def get_empty_storage(self):
+ w_result = Object()
+ terminator = self.space.fromcache(get_terminator_for_dicts)
+ w_result._init_empty(terminator)
+ return self.erase(w_result)
+
def switch_to_object_strategy(self, w_dict):
w_obj = self.unerase(w_dict.dstorage)
strategy = self.space.fromcache(ObjectDictStrategy)
dict_w = strategy.unerase(strategy.get_empty_storage())
w_dict.strategy = strategy
w_dict.dstorage = strategy.erase(dict_w)
- assert w_obj.getdict(self.space) is w_dict
+ assert w_obj.getdict(self.space) is w_dict or
w_obj._get_mapdict_map().terminator.w_cls is None
materialize_r_dict(self.space, w_obj, dict_w)
def getitem(self, w_dict, w_key):
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -898,7 +898,7 @@
raise NotImplementedError
def length(self):
- if self.setimplementation is not None:
+ if self.setimplementation is not None and self.len != -1:
return self.len - self.pos
return 0
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py
b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -954,6 +954,7 @@
withcelldict = False
withmethodcache = False
withidentitydict = False
+ withmapdict = False
FakeSpace.config = Config()
diff --git a/pypy/objspace/std/test/test_lengthhint.py
b/pypy/objspace/std/test/test_lengthhint.py
--- a/pypy/objspace/std/test/test_lengthhint.py
+++ b/pypy/objspace/std/test/test_lengthhint.py
@@ -6,7 +6,7 @@
SIZE = 4
ITEMS = range(SIZE)
- def _test_length_hint(self, w_obj):
+ def _test_length_hint(self, w_obj, w_mutate=None):
space = self.space
assert space.length_hint(w_obj, 8) == self.SIZE
@@ -18,6 +18,13 @@
space.next(w_iter)
assert space.length_hint(w_iter, 8) == self.SIZE - 1
+ if w_mutate is not None:
+ # Test handling of collections that enforce length
+ # immutability during iteration
+ space.call_function(w_mutate)
+ space.raises_w(space.w_RuntimeError, space.next, w_iter)
+ assert space.length_hint(w_iter, 8) == 0
+
def test_bytearray(self):
space = self.space
w_bytearray = space.call_function(space.w_bytearray,
@@ -31,16 +38,20 @@
self._test_length_hint(w_dict)
def test_dict_iterkeys(self):
- w_iterkeys = self.space.appexec([], """():
- return dict.fromkeys(%r).iterkeys()
- """ % self.ITEMS)
- self._test_length_hint(w_iterkeys)
+ space = self.space
+ w_iterkeys, w_mutate = space.fixedview(space.appexec([], """():
+ d = dict.fromkeys(%r)
+ return d.iterkeys(), d.popitem
+ """ % self.ITEMS), 2)
+ self._test_length_hint(w_iterkeys, w_mutate)
def test_dict_values(self):
- w_itervalues = self.space.appexec([], """():
- return dict.fromkeys(%r).itervalues()
- """ % self.ITEMS)
- self._test_length_hint(w_itervalues)
+ space = self.space
+ w_itervalues, w_mutate = space.fixedview(space.appexec([], """():
+ d = dict.fromkeys(%r)
+ return d.itervalues(), d.popitem
+ """ % self.ITEMS), 2)
+ self._test_length_hint(w_itervalues, w_mutate)
def test_frozenset(self):
space = self.space
@@ -50,7 +61,8 @@
def test_set(self):
space = self.space
w_set = space.call_function(space.w_set, space.wrap(self.ITEMS))
- self._test_length_hint(w_set)
+ w_mutate = space.getattr(w_set, space.wrap('pop'))
+ self._test_length_hint(w_set, w_mutate)
def test_list(self):
self._test_length_hint(self.space.wrap(self.ITEMS))
@@ -101,12 +113,19 @@
self._test_length_hint(W_Repeat(space, space.wrap(22),
space.wrap(self.SIZE)))
- def test_collections_deque(self):
+ def _setup_deque(self):
space = self.space
w_deque = W_Deque(space)
space.call_method(w_deque, '__init__', space.wrap(self.ITEMS))
- self._test_length_hint(w_deque)
- self._test_length_hint(w_deque.reviter())
+ w_mutate = space.getattr(w_deque, space.wrap('pop'))
+ return w_deque, w_mutate
+
+ def test_collections_deque(self):
+ self._test_length_hint(*self._setup_deque())
+
+ def test_collections_deque_rev(self):
+ w_deque, w_mutate = self._setup_deque()
+ self._test_length_hint(w_deque.reviter(), w_mutate)
def test_default(self):
space = self.space
diff --git a/pypy/objspace/std/test/test_mapdict.py
b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -1,7 +1,17 @@
from pypy.objspace.std.test.test_dictmultiobject import FakeSpace,
W_DictMultiObject
from pypy.objspace.std.mapdict import *
+class Config:
+ class objspace:
+ class std:
+ withsmalldicts = False
+ withcelldict = False
+ withmethodcache = False
+ withidentitydict = False
+ withmapdict = True
+
space = FakeSpace()
+space.config = Config
class Class(object):
def __init__(self, hasdict=True):
@@ -1061,3 +1071,11 @@
return A()
""")
assert w_dict.user_overridden_class
+
+def test_newdict_instance():
+ w_dict = space.newdict(instance=True)
+ assert type(w_dict.strategy) is MapDictStrategy
+
+class TestMapDictImplementationUsingnewdict(BaseTestRDictImplementation):
+ StrategyClass = MapDictStrategy
+ # NB: the get_impl method is not overwritten here, as opposed to above
diff --git a/pypy/pytest-A.cfg b/pypy/pytest-A.cfg
--- a/pypy/pytest-A.cfg
+++ b/pypy/pytest-A.cfg
@@ -1,5 +1,5 @@
cherrypick = ['interpreter', 'objspace/test', 'objspace/std', 'module']
-interp = ['translator/goal/pypy-c']
+interp = ['goal/pypy-c']
test_driver = ['test_all.py', '-A']
diff --git a/pypy/test_all.py b/pypy/test_all.py
--- a/pypy/test_all.py
+++ b/pypy/test_all.py
@@ -23,7 +23,8 @@
if len(sys.argv) == 1 and os.path.dirname(sys.argv[0]) in '.':
print >> sys.stderr, __doc__
sys.exit(2)
-
+ #Add toplevel repository dir to sys.path
+
sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
import pytest
import pytest_cov
sys.exit(pytest.main(plugins=[pytest_cov]))
diff --git a/pypy/tool/pytest/confpath.py b/pypy/tool/pytest/confpath.py
--- a/pypy/tool/pytest/confpath.py
+++ b/pypy/tool/pytest/confpath.py
@@ -1,8 +1,10 @@
import py
import pypy
+import rpython
from pypy.tool import lib_pypy
pypydir = py.path.local(pypy.__file__).dirpath()
+rpythondir = py.path.local(rpython.__file__).dirpath()
distdir = pypydir.dirpath()
testresultdir = distdir.join('testresult')
assert pypydir.check(dir=1)
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -11,8 +11,10 @@
import shutil
import sys
+import os
+#Add toplevel repository dir to sys.path
+sys.path.insert(0,os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
import py
-import os
import fnmatch
from rpython.tool.udir import udir
@@ -48,7 +50,7 @@
basename = 'pypy-c'
if sys.platform == 'win32':
basename += '.exe'
- pypy_c = basedir.join(basename)
+ pypy_c = basedir.join('pypy', 'goal', basename)
else:
pypy_c = py.path.local(override_pypy_c)
if not pypy_c.check():
diff --git a/pypy/bin/translatorshell.py b/rpython/bin/translatorshell.py
rename from pypy/bin/translatorshell.py
rename to rpython/bin/translatorshell.py
diff --git a/rpython/jit/backend/arm/test/support.py
b/rpython/jit/backend/arm/test/support.py
--- a/rpython/jit/backend/arm/test/support.py
+++ b/rpython/jit/backend/arm/test/support.py
@@ -14,6 +14,9 @@
def check_jumps(self, maxcount):
pass
+if not getattr(os, 'uname', None):
+ pytest.skip('cannot run arm tests on non-posix platform')
+
if os.uname()[1] == 'llaima.local':
AS =
'~/Code/arm-jit/android/android-ndk-r4b//build/prebuilt/darwin-x86/arm-eabi-4.4.0/arm-eabi/bin/as'
else:
diff --git a/rpython/jit/codewriter/effectinfo.py
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -79,9 +79,11 @@
OS_RAW_MALLOC_VARSIZE = 110
OS_RAW_FREE = 111
+ OS_JIT_FORCE_VIRTUAL = 120
+
# for debugging:
_OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL,
- OS_RAW_MALLOC_VARSIZE])
+ OS_RAW_MALLOC_VARSIZE, OS_JIT_FORCE_VIRTUAL])
def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
write_descrs_fields, write_descrs_arrays,
diff --git a/rpython/jit/codewriter/jtransform.py
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1393,6 +1393,8 @@
elif oopspec_name == 'jit.isvirtual':
kind = getkind(args[0].concretetype)
return SpaceOperation('%s_isvirtual' % kind, args, op.result)
+ elif oopspec_name == 'jit.force_virtual':
+ return self._handle_oopspec_call(op, args,
EffectInfo.OS_JIT_FORCE_VIRTUAL, EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)
else:
raise AssertionError("missing support for %r" % oopspec_name)
diff --git a/rpython/jit/codewriter/support.py
b/rpython/jit/codewriter/support.py
--- a/rpython/jit/codewriter/support.py
+++ b/rpython/jit/codewriter/support.py
@@ -1,24 +1,24 @@
import sys
-from rpython.rtyper.lltypesystem import lltype, rclass, rffi, llmemory
-from rpython.rtyper.ootypesystem import ootype
-from rpython.rtyper import rlist
-from rpython.rtyper.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
-from rpython.rtyper.lltypesystem.module import ll_math
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rtyper.ootypesystem import rdict as oo_rdict
-from rpython.rtyper.llinterp import LLInterpreter
-from rpython.rtyper.extregistry import ExtRegistryEntry
-from rpython.translator.simplify import get_funcobj
-from rpython.translator.unsimplify import split_block
+
+from rpython.annotator import model as annmodel
+from rpython.annotator.policy import AnnotatorPolicy
from rpython.flowspace.model import Variable, Constant
-from rpython.translator.translator import TranslationContext
-from rpython.annotator.policy import AnnotatorPolicy
-from rpython.annotator import model as annmodel
-from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
from rpython.jit.metainterp.typesystem import deref
from rpython.rlib import rgc
-from rpython.rlib.jit import elidable
+from rpython.rlib.jit import elidable, oopspec
from rpython.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
+from rpython.rtyper import rlist
+from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
+from rpython.rtyper.extregistry import ExtRegistryEntry
+from rpython.rtyper.llinterp import LLInterpreter
+from rpython.rtyper.lltypesystem import lltype, rclass, rffi, llmemory, rstr
as ll_rstr, rdict as ll_rdict
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.lltypesystem.module import ll_math
+from rpython.rtyper.ootypesystem import ootype, rdict as oo_rdict
+from rpython.translator.simplify import get_funcobj
+from rpython.translator.translator import TranslationContext
+from rpython.translator.unsimplify import split_block
+
def getargtypes(annotator, values):
if values is None: # for backend tests producing stand-alone exe's
@@ -213,10 +213,12 @@
_ll_5_list_ll_arraycopy = rgc.ll_arraycopy
+
@elidable
def _ll_1_gc_identityhash(x):
return lltype.identityhash(x)
+
# the following function should not be "@elidable": I can think of
# a corner case in which id(const) is constant-folded, and then 'const'
# disappears and is collected too early (possibly causing another object
@@ -224,6 +226,8 @@
def _ll_1_gc_id(ptr):
return llop.gc_id(lltype.Signed, ptr)
+
+@oopspec("jit.force_virtual(inst)")
def _ll_1_jit_force_virtual(inst):
return llop.jit_force_virtual(lltype.typeOf(inst), inst)
diff --git a/rpython/jit/metainterp/history.py
b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -976,11 +976,9 @@
def get_all_jitcell_tokens(self):
tokens = [t() for t in self.jitcell_token_wrefs]
if None in tokens:
- assert False, "get_all_jitcell_tokens will not work as "+\
- "loops have been freed"
+ assert False, ("get_all_jitcell_tokens will not work as "
+ "loops have been freed")
return tokens
-
-
def check_history(self, expected=None, **check):
insns = {}
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py
b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -1,12 +1,13 @@
+from rpython.jit.codewriter.effectinfo import EffectInfo
+from rpython.jit.metainterp.executor import execute
from rpython.jit.codewriter.heaptracker import vtable2descr
-from rpython.jit.metainterp.executor import execute
from rpython.jit.metainterp.history import Const, ConstInt, BoxInt
from rpython.jit.metainterp.optimizeopt import optimizer
+from rpython.jit.metainterp.optimizeopt.optimizer import OptValue, REMOVED
from rpython.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
descrlist_dict, sort_descrs)
from rpython.jit.metainterp.resoperation import rop, ResOperation
from rpython.rlib.objectmodel import we_are_translated
-from rpython.jit.metainterp.optimizeopt.optimizer import OptValue
class AbstractVirtualValue(optimizer.OptValue):
@@ -386,6 +387,24 @@
self.make_equal_to(box, vvalue)
return vvalue
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ return
+ self.emit_operation(op)
+
+ def optimize_GUARD_NOT_FORCED(self, op):
+ if self.last_emitted_operation is REMOVED:
+ return
+ self.emit_operation(op)
+
+ def optimize_CALL_MAY_FORCE(self, op):
+ effectinfo = op.getdescr().get_extra_info()
+ oopspecindex = effectinfo.oopspecindex
+ if oopspecindex == EffectInfo.OS_JIT_FORCE_VIRTUAL:
+ if self._optimize_JIT_FORCE_VIRTUAL(op):
+ return
+ self.emit_operation(op)
+
def optimize_VIRTUAL_REF(self, op):
indexbox = op.getarg(1)
#
@@ -429,7 +448,7 @@
# - set 'virtual_token' to TOKEN_NONE
args = [op.getarg(0), ConstInt(vrefinfo.TOKEN_NONE)]
seo(ResOperation(rop.SETFIELD_GC, args, None,
- descr = vrefinfo.descr_virtual_token))
+ descr=vrefinfo.descr_virtual_token))
# Note that in some cases the virtual in op.getarg(1) has been forced
# already. This is fine. In that case, and *if* a residual
# CALL_MAY_FORCE suddenly turns out to access it, then it will
@@ -437,6 +456,20 @@
# will work too (but just be a little pointless, as the structure
# was already forced).
+ def _optimize_JIT_FORCE_VIRTUAL(self, op):
+ vref = self.getvalue(op.getarg(1))
+ vrefinfo = self.optimizer.metainterp_sd.virtualref_info
+ if vref.is_virtual():
+ tokenvalue = vref.getfield(vrefinfo.descr_virtual_token, None)
+ if (tokenvalue is not None and tokenvalue.is_constant() and
+ tokenvalue.box.getint() == vrefinfo.TOKEN_NONE):
+ forcedvalue = vref.getfield(vrefinfo.descr_forced, None)
+ if forcedvalue is not None and not forcedvalue.is_null():
+ self.make_equal_to(op.result, forcedvalue)
+ self.last_emitted_operation = REMOVED
+ return True
+ return False
+
def optimize_GETFIELD_GC(self, op):
value = self.getvalue(op.getarg(0))
# If this is an immutable field (as indicated by op.is_always_pure())
diff --git a/rpython/jit/metainterp/test/support.py
b/rpython/jit/metainterp/test/support.py
--- a/rpython/jit/metainterp/test/support.py
+++ b/rpython/jit/metainterp/test/support.py
@@ -160,16 +160,17 @@
class JitMixin:
basic = True
+
def check_resops(self, expected=None, **check):
get_stats().check_resops(expected=expected, **check)
+
def check_simple_loop(self, expected=None, **check):
get_stats().check_simple_loop(expected=expected, **check)
-
-
def check_trace_count(self, count): # was check_loop_count
# The number of traces compiled
assert get_stats().compiled_count == count
+
def check_trace_count_at_most(self, count):
assert get_stats().compiled_count <= count
@@ -178,11 +179,12 @@
def check_target_token_count(self, count):
tokens = get_stats().get_all_jitcell_tokens()
- n = sum ([len(t.target_tokens) for t in tokens])
+ n = sum([len(t.target_tokens) for t in tokens])
assert n == count
def check_enter_count(self, count):
assert get_stats().enter_count == count
+
def check_enter_count_at_most(self, count):
assert get_stats().enter_count <= count
@@ -192,6 +194,7 @@
def check_aborted_count(self, count):
assert get_stats().aborted_count == count
+
def check_aborted_count_at_least(self, count):
assert get_stats().aborted_count >= count
diff --git a/rpython/jit/metainterp/test/test_virtualref.py
b/rpython/jit/metainterp/test/test_virtualref.py
--- a/rpython/jit/metainterp/test/test_virtualref.py
+++ b/rpython/jit/metainterp/test/test_virtualref.py
@@ -1,19 +1,20 @@
import py
-from rpython.rtyper.lltypesystem import lltype, llmemory, lloperation
+
+from rpython.rtyper.lltypesystem import lltype, lloperation
from rpython.rtyper.exceptiondata import UnknownException
from rpython.rlib.jit import JitDriver, dont_look_inside, vref_None
from rpython.rlib.jit import virtual_ref, virtual_ref_finish, InvalidVirtualRef
from rpython.rlib.jit import non_virtual_ref
from rpython.rlib.objectmodel import compute_unique_id
-from rpython.jit.metainterp.test.support import LLJitMixin, OOJitMixin,
_get_jitcodes
+from rpython.jit.metainterp.test.support import LLJitMixin, _get_jitcodes
from rpython.jit.metainterp.resoperation import rop
from rpython.jit.metainterp.virtualref import VirtualRefInfo
+
debug_print = lloperation.llop.debug_print
-class VRefTests:
-
+class VRefTests(object):
def finish_setup_for_interp_operations(self):
self.vrefinfo = VirtualRefInfo(self.warmrunnerstate)
self.cw.setup_vrefinfo(self.vrefinfo)
@@ -115,8 +116,8 @@
from rpython.jit.metainterp.resume import ResumeDataDirectReader
cpu = self.metainterp.cpu
cpu.get_latest_value_count = lambda df: len(guard_op.getfailargs())
- cpu.get_latest_value_int = lambda
df,i:guard_op.getfailargs()[i].getint()
- cpu.get_latest_value_ref = lambda
df,i:guard_op.getfailargs()[i].getref_base()
+ cpu.get_latest_value_int = lambda df, i:
guard_op.getfailargs()[i].getint()
+ cpu.get_latest_value_ref = lambda df, i:
guard_op.getfailargs()[i].getref_base()
cpu.clear_latest_values = lambda count: None
class FakeMetaInterpSd:
callinfocollection = None
@@ -418,15 +419,18 @@
self.check_aborted_count(0)
def test_jit_force_virtual_seen(self):
- myjitdriver = JitDriver(greens = [], reds = ['n'])
- #
+ myjitdriver = JitDriver(greens=[], reds=['n'])
+
A = lltype.GcArray(lltype.Signed)
- class XY:
+
+ class XY(object):
pass
- class ExCtx:
+
+ class ExCtx(object):
pass
exctx = ExCtx()
- #
+ escapes = []
+
def f(n):
while n > 0:
myjitdriver.can_enter_jit(n=n)
@@ -434,16 +438,16 @@
xy = XY()
xy.n = n
exctx.topframeref = vref = virtual_ref(xy)
+ escapes.append(xy)
xy.next1 = lltype.malloc(A, 0)
n = exctx.topframeref().n - 1
- xy.next1 = lltype.nullptr(A)
exctx.topframeref = vref_None
virtual_ref_finish(vref, xy)
return 1
#
res = self.meta_interp(f, [15])
assert res == 1
- self.check_resops(new_with_vtable=4, # vref, xy
+ self.check_resops(new_with_vtable=2, # xy
new_array=2) # next1
self.check_aborted_count(0)
@@ -656,6 +660,34 @@
res = self.meta_interp(f, [10])
assert res == 0
+ def test_force_virtual_vref(self):
+ myjitdriver = JitDriver(greens=[], reds=['n', 'ec'])
+
+ class ExecutionContext(object):
+ pass
+
+ class Frame(object):
+ def __init__(self, x):
+ self.x = x
+
+ def f(n):
+ ec = ExecutionContext()
+ while n > 0:
+ myjitdriver.jit_merge_point(n=n, ec=ec)
+ frame = Frame(1)
+ ec.topframeref = virtual_ref(frame)
+ n -= ec.topframeref().x
+ frame_vref = ec.topframeref
+ ec.topframeref = vref_None
+ virtual_ref_finish(frame_vref, frame)
+ return n
+ res = self.meta_interp(f, [10])
+ assert res == 0
+ self.check_resops({
+ 'int_sub': 2, 'int_gt': 2, 'jump': 1, 'guard_true': 2,
+ 'force_token': 2, 'setfield_gc': 1
+ })
+
class TestLLtype(VRefTests, LLJitMixin):
pass
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -310,10 +310,7 @@
def decorate(func):
from rpython.tool.sourcetools import compile2
#
- def get_printable_location():
- return name
- jitdriver = JitDriver(get_printable_location=get_printable_location,
- greens=[], reds='auto', name=name)
+ jitdriver = JitDriver(greens=[], reds='auto', name=name)
#
args = ','.join(['a%d' % i for i in range(func.func_code.co_argcount)])
source = """def callback_with_jitdriver(%(args)s):
@@ -484,8 +481,11 @@
self.autoreds = True
self.reds = []
self.numreds = None # see warmspot.autodetect_jit_markers_redvars
- assert confirm_enter_jit is None, (
- "reds='auto' is not compatible with confirm_enter_jit")
+ for hook in [
+ get_jitcell_at, set_jitcell_at, get_printable_location,
+ confirm_enter_jit
+ ]:
+ assert hook is None, "reds='auto' is not compatible with
JitDriver hooks"
else:
if reds is not None:
self.reds = reds
diff --git a/rpython/rlib/unicodedata/test/test_ucd.py
b/rpython/rlib/unicodedata/test/test_ucd.py
--- a/rpython/rlib/unicodedata/test/test_ucd.py
+++ b/rpython/rlib/unicodedata/test/test_ucd.py
@@ -1,9 +1,9 @@
+from rpython.rlib.runicode import code_to_unichr
+from rpython.rlib.unicodedata import unicodedb_5_2_0
from rpython.rtyper.test.tool import BaseRtypingTest, LLRtypeMixin
-from rpython.rlib.unicodedata import unicodedb_5_2_0
-from rpython.rlib.unicodedata.ucd import code_to_unichr
+
class TestTranslated(BaseRtypingTest, LLRtypeMixin):
-
def test_translated(self):
def f(n):
if n == 0:
diff --git a/rpython/rlib/unicodedata/test/test_unicodedata.py
b/rpython/rlib/unicodedata/test/test_unicodedata.py
--- a/rpython/rlib/unicodedata/test/test_unicodedata.py
+++ b/rpython/rlib/unicodedata/test/test_unicodedata.py
@@ -1,11 +1,15 @@
+import random
+import unicodedata
+
import py
+
from rpython.rlib.unicodedata import unicodedb_3_2_0, unicodedb_5_2_0
+
class TestUnicodeData(object):
def setup_class(cls):
- import random, unicodedata
if unicodedata.unidata_version != '5.2.0':
- skip('Needs python with unicode 5.2.0 database.')
+ py.test.skip('Needs python with unicode 5.2.0 database.')
seed = random.getrandbits(32)
print "random seed: ", seed
@@ -29,14 +33,12 @@
py.test.raises(KeyError, unicodedb_5_2_0.name, ord(chr))
def test_compare_functions(self):
- import unicodedata # CPython implementation
-
def getX(fun, code):
try:
return getattr(unicodedb_5_2_0, fun)(code)
except KeyError:
return -1
-
+
for code in range(0x10000):
char = unichr(code)
assert unicodedata.digit(char, -1) == getX('digit', code)
@@ -73,5 +75,3 @@
assert unicodedb_5_2_0.lookup('BENZENE RING WITH CIRCLE') == 9187
py.test.raises(KeyError, unicodedb_3_2_0.lookup, 'BENZENE RING WITH
CIRCLE')
py.test.raises(KeyError, unicodedb_3_2_0.name, 9187)
-
-
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit