[pypy-commit] pypy guard-compatible: a new decorator elidable_compatible, with a docstring how I want things to work

cfbolz pypy.commits at gmail.com
Sat Mar 12 17:25:20 EST 2016


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r83000:1fb0c5a8a04e
Date: 2016-03-12 22:38 +0100
http://bitbucket.org/pypy/pypy/changeset/1fb0c5a8a04e/

Log:	a new decorator elidable_compatible, with a docstring how I want
	things to work

diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -93,6 +93,8 @@
     * force_virtualizable - a performance hint to force the virtualizable early
                             (useful e.g. for python generators that are going
                             to be read later anyway)
+    * promote_compatible  - an internal hint used in the implementation of
+                            elidable_compatible
     """
     return x
 
@@ -126,6 +128,42 @@
 def promote_string(x):
     return hint(x, promote_string=True)
 
+def elidable_compatible():
+    """ func must be a function of at least one argument. That first argument
+    must be pointer-like (XXX for now?) The behaviour of @elidable_compatible
+    is as follows:
+
+    it turns a call to func like this:
+    res = func(a1, *args)
+
+    into something that behaves similar to this:
+    promote(a1)
+    res = func(a1, *args)
+
+    However, the promote of a1 is not implemented with a guard_value. Instead,
+    it uses guard_compatible, which is less strict and causes less failures.
+    More precisely, executing the guard_compatible(x) will only fail if
+    func(x, *args) != func(a1, *args)
+
+    In this, a1 must not be None.
+
+    This works particularly well if func maps many different values a1 to a
+    single value res. If func is an injection, there is no reason to not simply
+    use a regular promote.
+
+    XXX what happens if the *args are not constant?
+    XXX we need a better name
+    """
+    def decorate(func):
+        elidable(func)
+        def wrapped_func(x, *args):
+            assert x is not None
+            x = hint(x, promote_compatible=True)
+            return func(x, *args)
+        return wrapped_func
+    return decorate
+
+
 def dont_look_inside(func):
     """ Make sure the JIT does not trace inside decorated function
     (it becomes a call instead)
diff --git a/rpython/rlib/test/test_jit.py b/rpython/rlib/test/test_jit.py
--- a/rpython/rlib/test/test_jit.py
+++ b/rpython/rlib/test/test_jit.py
@@ -5,7 +5,7 @@
 from rpython.rlib.jit import (hint, we_are_jitted, JitDriver, elidable_promote,
     JitHintError, oopspec, isconstant, conditional_call,
     elidable, unroll_safe, dont_look_inside,
-    enter_portal_frame, leave_portal_frame)
+    enter_portal_frame, leave_portal_frame, elidable_compatible)
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rtyper.test.tool import BaseRtypingTest
 from rpython.rtyper.lltypesystem import lltype
@@ -143,6 +143,27 @@
         res = self.interpret(f, [2])
         assert res == 5
 
+    def test_elidable_promote(self):
+        class A(object):
+            pass
+        a1 = A()
+        a1.x = 1
+        a2 = A()
+        a2.x = 2
+        @elidable_compatible()
+        def g(a):
+            return a.x
+        def f(x):
+            if x == 1:
+                a = a1
+            else:
+                a = a2
+            return g(a)
+        res = self.interpret(f, [1])
+        assert res == 1
+        res = self.interpret(f, [4])
+        assert res == 2
+
     def test_elidable_promote_args(self):
         @elidable_promote(promote_args='0')
         def g(func, x):


More information about the pypy-commit mailing list