[pypy-commit] pypy default: Try heuristically to check when running on top of CPython

arigo noreply at buildbot.pypy.org
Wed Feb 22 18:32:17 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r52763:1c381a211cb1
Date: 2012-02-22 18:23 +0100
http://bitbucket.org/pypy/pypy/changeset/1c381a211cb1/

Log:	Try heuristically to check when running on top of CPython that the
	arguments of jitdriver.jit_merge_point() have been specified in the
	correct order. Unsure that all cases are covered correctly, but
	should mostly work.

diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -450,6 +450,7 @@
             assert v in self.reds
         self._alllivevars = dict.fromkeys(
             [name for name in self.greens + self.reds if '.' not in name])
+        self._heuristic_order = {}   # check if 'reds' and 'greens' are ordered
         self._make_extregistryentries()
         self.get_jitcell_at = get_jitcell_at
         self.set_jitcell_at = set_jitcell_at
@@ -461,13 +462,59 @@
     def _freeze_(self):
         return True
 
+    def _check_arguments(self, livevars):
+        assert dict.fromkeys(livevars) == self._alllivevars
+        # check heuristically that 'reds' and 'greens' are ordered as
+        # the JIT will need them to be: first INTs, then REFs, then
+        # FLOATs.
+        if len(self._heuristic_order) < len(livevars):
+            from pypy.rlib.rarithmetic import (r_singlefloat, r_longlong,
+                                               r_ulonglong)
+            added = False
+            for var, value in livevars.items():
+                if var not in self._heuristic_order:
+                    if isinstance(value, (r_longlong, r_ulonglong)):
+                        assert 0, ("should not pass a r_longlong argument for "
+                                   "now, because on 32-bit machines it would "
+                                   "need to be ordered as a FLOAT")
+                    elif isinstance(value, (int, long, r_singlefloat)):
+                        kind = '1:INT'
+                    elif isinstance(value, float):
+                        kind = '3:FLOAT'
+                    elif isinstance(value, (str, unicode)) and len(value) != 1:
+                        kind = '2:REF'
+                    elif isinstance(value, (list, dict)):
+                        kind = '2:REF'
+                    elif (hasattr(value, '__class__')
+                          and value.__class__.__module__ != '__builtin__'):
+                        if hasattr(value, '_freeze_'):
+                            continue   # value._freeze_() is better not called
+                        elif getattr(value, '_alloc_flavor_', 'gc') == 'gc':
+                            kind = '2:REF'
+                        else:
+                            kind = '1:INT'
+                    else:
+                        continue
+                    self._heuristic_order[var] = kind
+                    added = True
+            if added:
+                for color in ('reds', 'greens'):
+                    lst = getattr(self, color)
+                    allkinds = [self._heuristic_order.get(name, '?')
+                                for name in lst]
+                    kinds = [k for k in allkinds if k != '?']
+                    assert kinds == sorted(kinds), (
+                        "bad order of %s variables in the jitdriver: "
+                        "must be INTs, REFs, FLOATs; got %r" %
+                        (color, allkinds))
+
     def jit_merge_point(_self, **livevars):
         # special-cased by ExtRegistryEntry
-        assert dict.fromkeys(livevars) == _self._alllivevars
+        _self._check_arguments(livevars)
 
     def can_enter_jit(_self, **livevars):
         # special-cased by ExtRegistryEntry
-        assert dict.fromkeys(livevars) == _self._alllivevars
+        _self._check_arguments(livevars)
 
     def loop_header(self):
         # special-cased by ExtRegistryEntry
diff --git a/pypy/rlib/test/test_jit.py b/pypy/rlib/test/test_jit.py
--- a/pypy/rlib/test/test_jit.py
+++ b/pypy/rlib/test/test_jit.py
@@ -146,6 +146,38 @@
         res = self.interpret(f, [-234])
         assert res == 1
 
+    def test_argument_order_ok(self):
+        myjitdriver = JitDriver(greens=['i1', 'r1', 'f1'], reds=[])
+        class A(object):
+            pass
+        myjitdriver.jit_merge_point(i1=42, r1=A(), f1=3.5)
+        # assert did not raise
+
+    def test_argument_order_wrong(self):
+        myjitdriver = JitDriver(greens=['r1', 'i1', 'f1'], reds=[])
+        class A(object):
+            pass
+        e = raises(AssertionError,
+                   myjitdriver.jit_merge_point, i1=42, r1=A(), f1=3.5)
+
+    def test_argument_order_more_precision_later(self):
+        myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
+        class A(object):
+            pass
+        myjitdriver.jit_merge_point(i1=42, r1=None, r2=None, f1=3.5)
+        e = raises(AssertionError,
+                   myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
+        assert "got ['2:REF', '1:INT', '?', '3:FLOAT']" in repr(e.value)
+
+    def test_argument_order_more_precision_later_2(self):
+        myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
+        class A(object):
+            pass
+        myjitdriver.jit_merge_point(i1=42, r1=None, r2=A(), f1=3.5)
+        e = raises(AssertionError,
+                   myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
+        assert "got ['2:REF', '1:INT', '2:REF', '3:FLOAT']" in repr(e.value)
+
 
 class TestJITLLtype(BaseTestJIT, LLRtypeMixin):
     pass


More information about the pypy-commit mailing list