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

Reply via email to