[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