[pypy-commit] pypy faster-isinstance: Implement specialize.arg_or_var that creates either a specialization based
fijal
noreply at buildbot.pypy.org
Thu Sep 29 00:36:17 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: faster-isinstance
Changeset: r47663:b508d452f1ef
Date: 2011-09-28 13:33 -0300
http://bitbucket.org/pypy/pypy/changeset/b508d452f1ef/
Log: Implement specialize.arg_or_var that creates either a specialization
based on a value or specialcase when it's not a constant.
Implement objectmodel.is_constant that can be used with that
diff --git a/pypy/annotation/policy.py b/pypy/annotation/policy.py
--- a/pypy/annotation/policy.py
+++ b/pypy/annotation/policy.py
@@ -1,6 +1,6 @@
# base annotation policy for specialization
from pypy.annotation.specialize import default_specialize as default
-from pypy.annotation.specialize import specialize_argvalue, specialize_argtype, specialize_arglistitemtype
+from pypy.annotation.specialize import specialize_argvalue, specialize_argtype, specialize_arglistitemtype, specialize_arg_or_var
from pypy.annotation.specialize import memo, specialize_call_location
# for some reason, model must be imported first,
# or we create a cycle.
@@ -73,6 +73,7 @@
default_specialize = staticmethod(default)
specialize__memo = staticmethod(memo)
specialize__arg = staticmethod(specialize_argvalue) # specialize:arg(N)
+ specialize__arg_or_var = staticmethod(specialize_arg_or_var)
specialize__argtype = staticmethod(specialize_argtype) # specialize:argtype(N)
specialize__arglistitemtype = staticmethod(specialize_arglistitemtype)
specialize__call_location = staticmethod(specialize_call_location)
diff --git a/pypy/annotation/specialize.py b/pypy/annotation/specialize.py
--- a/pypy/annotation/specialize.py
+++ b/pypy/annotation/specialize.py
@@ -353,6 +353,16 @@
key = tuple(key)
return maybe_star_args(funcdesc, key, args_s)
+def specialize_arg_or_var(funcdesc, args_s, *argindices):
+ for argno in argindices:
+ if not args_s[argno].is_constant():
+ break
+ else:
+ # all constant
+ return specialize_argvalue(funcdesc, args_s, *argindices)
+ # some not constant
+ return maybe_star_args(funcdesc, None, args_s)
+
def specialize_argtype(funcdesc, args_s, *argindices):
key = tuple([args_s[i].knowntype for i in argindices])
for cls in key:
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -1194,6 +1194,20 @@
assert len(executedesc._cache[(0, 'star', 2)].startblock.inputargs) == 4
assert len(executedesc._cache[(1, 'star', 3)].startblock.inputargs) == 5
+ def test_specialize_arg_or_var(self):
+ def f(a):
+ return 1
+ f._annspecialcase_ = 'specialize:arg_or_var(0)'
+
+ def fn(a):
+ return f(3) + f(a)
+
+ a = self.RPythonAnnotator()
+ a.build_types(fn, [int])
+ executedesc = a.bookkeeper.getdesc(f)
+ assert sorted(executedesc._cache.keys()) == [None, (3,)]
+ # we got two different special
+
def test_specialize_call_location(self):
def g(a):
return a
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -46,6 +46,17 @@
return decorated_func
+ def arg_or_var(self, *args):
+ """ Same as arg, but additionally allow for a 'variable' annotation,
+ that would simply be a situation where designated arg is not
+ a constant
+ """
+ def decorated_func(func):
+ func._annspecialcase_ = 'specialize:arg_or_var' + self._wrap(args)
+ return func
+
+ return decorated_func
+
def argtype(self, *args):
""" Specialize function based on types of arguments on given positions.
@@ -165,6 +176,25 @@
def keepalive_until_here(*values):
pass
+def is_constant(thing):
+ return True
+
+class Entry(ExtRegistryEntry):
+ _about_ = is_constant
+
+ def compute_result_annotation(self, s_arg):
+ from pypy.annotation import model
+ r = model.SomeBool()
+ if s_arg.is_constant():
+ r.const = True
+ else:
+ r.const = False
+ return r
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ return hop.inputconst(lltype.Bool, hop.s_result.const)
+
# ____________________________________________________________
class FREED_OBJECT(object):
diff --git a/pypy/rlib/test/test_objectmodel.py b/pypy/rlib/test/test_objectmodel.py
--- a/pypy/rlib/test/test_objectmodel.py
+++ b/pypy/rlib/test/test_objectmodel.py
@@ -339,6 +339,19 @@
res = self.interpret(f, [42])
assert res == 84
+ def test_isconstant(self):
+ from pypy.rlib.objectmodel import is_constant, specialize
+
+ @specialize.arg_or_var(0)
+ def f(arg):
+ if is_constant(arg):
+ return 1
+ return 10
+
+ def fn(arg):
+ return f(arg) + f(3)
+
+ assert self.interpret(fn, [15]) == 11
class TestLLtype(BaseTestObjectModel, LLRtypeMixin):
@@ -451,5 +464,4 @@
if llop.opname == 'malloc_varsize':
break
assert llop.args[2] is graph.startblock.inputargs[0]
-
More information about the pypy-commit
mailing list