[pypy-commit] pypy default: Merge a branch that makes space.isinstance(w_obj, <a constant>) do a fastpath
fijal
noreply at buildbot.pypy.org
Thu Sep 29 04:40:41 CEST 2011
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r47667:ffbf1bcf89d6
Date: 2011-09-28 23:39 -0300
http://bitbucket.org/pypy/pypy/changeset/ffbf1bcf89d6/
Log: Merge a branch that makes space.isinstance(w_obj, <a constant>) do a
fastpath with isinstance(w_obj, <an RPython class representing the
constant>)
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/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -6,6 +6,7 @@
from pypy.interpreter.typedef import default_identity_hash
from pypy.tool.sourcetools import compile2, func_with_new_name
from pypy.module.__builtin__.interp_classobj import W_InstanceObject
+from pypy.rlib.objectmodel import specialize
def object_getattribute(space):
"Utility that returns the app-level descriptor object.__getattribute__."
@@ -507,6 +508,7 @@
def issubtype(space, w_sub, w_type):
return space._type_issubtype(w_sub, w_type)
+ @specialize.arg_or_var(2)
def isinstance(space, w_inst, w_type):
return space.wrap(space._type_isinstance(w_inst, w_type))
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -7,7 +7,7 @@
from pypy.objspace.std import (builtinshortcut, stdtypedef, frame, model,
transparent, callmethod, proxyobject)
from pypy.objspace.descroperation import DescrOperation, raiseattrerror
-from pypy.rlib.objectmodel import instantiate, r_dict, specialize
+from pypy.rlib.objectmodel import instantiate, r_dict, specialize, is_constant
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.rarithmetic import base_int, widen
from pypy.rlib.objectmodel import we_are_translated
@@ -83,6 +83,12 @@
if self.config.objspace.std.withtproxy:
transparent.setup(self)
+ for type, classes in self.model.typeorder.iteritems():
+ if len(classes) == 3:
+ # W_Root, AnyXxx and actual object
+ self.gettypefor(type).interplevel_cls = classes[0][0]
+
+
def get_builtin_types(self):
return self.builtin_types
@@ -567,10 +573,19 @@
return self.wrap(w_sub.issubtype(w_type))
raise OperationError(self.w_TypeError, self.wrap("need type objects"))
+ @specialize.arg_or_var(2)
def _type_isinstance(self, w_inst, w_type):
- if isinstance(w_type, W_TypeObject):
- return self.type(w_inst).issubtype(w_type)
- raise OperationError(self.w_TypeError, self.wrap("need type object"))
+ if not isinstance(w_type, W_TypeObject):
+ raise OperationError(self.w_TypeError,
+ self.wrap("need type object"))
+ if is_constant(w_type):
+ cls = w_type.interplevel_cls
+ if cls is not None:
+ assert w_inst is not None
+ if isinstance(w_inst, cls):
+ return True
+ return self.type(w_inst).issubtype(w_type)
+ @specialize.arg_or_var(2)
def isinstance_w(space, w_inst, w_type):
return space._type_isinstance(w_inst, w_type)
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -115,6 +115,9 @@
# of the __new__ is an instance of the type
w_bltin_new = None
+ interplevel_cls = None # not None for prebuilt instances of
+ # interpreter-level types
+
@dont_look_inside
def __init__(w_self, space, name, bases_w, dict_w,
overridetypedef=None):
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,22 @@
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()
+ r.const = s_arg.is_constant()
+ 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