[pypy-svn] r13058 - in pypy/dist/pypy: annotation translator translator/test
pedronis at codespeak.net
pedronis at codespeak.net
Sat Jun 4 18:28:53 CEST 2005
Author: pedronis
Date: Sat Jun 4 18:28:53 2005
New Revision: 13058
Modified:
pypy/dist/pypy/annotation/bookkeeper.py
pypy/dist/pypy/annotation/unaryop.py
pypy/dist/pypy/translator/annrpython.py
pypy/dist/pypy/translator/test/test_annrpython.py
Log:
for less confusion and presision move pbc call sites info computation at fix-point.
Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py (original)
+++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jun 4 18:28:53 2005
@@ -64,8 +64,13 @@
self.argtypes_spec_callsite_results = {}
self.pbc_maximal_access_sets = UnionFind(PBCAccessSet)
- self.pbc_maximal_call_families = UnionFind(PBCCallFamily)
- self.pbc_callables = {}
+ # can be precisely computed only at fix-point, see
+ # compute_at_fixpoint
+ self.pbc_maximal_call_families = None
+ self.pbc_callables = None
+
+ self.pbc_call_sites = {}
+
# import ordering hack
global BUILTIN_ANALYZERS
@@ -82,6 +87,15 @@
del TLS.bookkeeper
del self.position_key
+ def compute_at_fixpoint(self):
+ self.pbc_maximal_call_families = UnionFind(PBCCallFamily)
+ self.pbc_callables = {}
+
+ for (fn, block, i), shape in self.pbc_call_sites.iteritems():
+ assert block.operations[i].opname in ('call_args', 'simple_call')
+ pbc = self.annotator.binding(block.operations[i].args[0], extquery=True)
+ self.consider_pbc_call(pbc, shape, position=(fn, block, i))
+
def getclassdef(self, cls):
"""Get the ClassDef associated with the given user cls."""
if cls is object:
@@ -298,38 +312,33 @@
return unionof(*actuals)
- def mark_callable(self, callable):
- classdef, func = callable
-
- if hasattr(func, 'im_func') and func.im_self is None:
- # consider unbound methods and the undelying functions as the same
- func = func.im_func
-
- self.pbc_callables.setdefault(func,{})[callable] = True
+ def consider_pbc_call(self, pbc, shape, position=None): # computation done at fix-point
+ if not isinstance(pbc, SomePBC):
+ return
- def pbc_call(self, pbc, args):
nonnullcallables = []
- patterns = {}
- results = []
- # extract args shape
- shape = args.rawshape()
-
for func, classdef in pbc.prebuiltinstances.items():
if func is None:
continue
- if isclassdef(classdef):
- s_self = SomeInstance(classdef)
- args1 = args.prepend(s_self)
- else:
+ if not isclassdef(classdef):
classdef = None
- args1 = args
- results.append(self.pycall(func, args1))
+
+ # if class => consider __init__ too
+ if isinstance(func, (type, ClassType)) and \
+ func.__module__ != '__builtin__':
+ assert classdef is None
+ dontcare, s_init = self.get_s_init(func, position=position)
+ if s_init is not None:
+ init_shape = (shape[0]+1,) + shape[1:]
+ self.consider_pbc_call(s_init, init_shape)
callable = (classdef, func)
- self.mark_callable(callable)
+ if hasattr(func, 'im_func') and func.im_self is None:
+ # consider unbound methods and the undelying functions as the same
+ func = func.im_func
+ self.pbc_callables.setdefault(func,{})[callable] = True
nonnullcallables.append(callable)
- patterns[shape] = True
-
+
if nonnullcallables:
call_families = self.pbc_maximal_call_families
@@ -337,46 +346,77 @@
for obj in nonnullcallables:
dontcare, rep, callfamily = call_families.union(rep, obj)
- callfamily.patterns.update(patterns)
+ callfamily.patterns.update({shape: True})
+
+ def pbc_call(self, pbc, args, implicit_init):
+ if not implicit_init:
+ fn, block, i = self.position_key
+ assert block.operations[i].opname in ('call_args', 'simple_call')
+ assert self.annotator.binding(block.operations[i].args[0], extquery=True) is pbc
+
+ # extract shape from args
+ shape = args.rawshape()
+ if self.position_key in self.pbc_call_sites:
+ assert self.pbc_call_sites[self.position_key] == shape
+ else:
+ self.pbc_call_sites[self.position_key] = shape
+
+ results = []
+ for func, classdef in pbc.prebuiltinstances.items():
+ if func is None:
+ continue
+ if isclassdef(classdef):
+ s_self = SomeInstance(classdef)
+ args1 = args.prepend(s_self)
+ else:
+ args1 = args
+ results.append(self.pycall(func, args1))
return unionof(*results)
+ def get_s_init(self, cls, position=None):
+ specialize = getattr(cls, "_specialize_", False)
+ if specialize:
+ if specialize == "location":
+ cls = self.specialize_by_key(cls, position,
+ name="%s__At_%s" % (cls.__name__,
+ position_name(position)))
+ else:
+ raise Exception, \
+ "unsupported specialization type '%s'"%(specialize,)
+
+ classdef = self.getclassdef(cls)
+ init = getattr(cls, '__init__', None)
+ if init is not None and init != object.__init__:
+ # don't record the access of __init__ on the classdef
+ # because it is not a dynamic attribute look-up, but
+ # merely a static function call
+ if hasattr(init, 'im_func'):
+ init = init.im_func
+ else:
+ assert isinstance(init, BuiltinMethodType)
+ s_init = self.immutablevalue(init)
+ return classdef, s_init
+ else:
+ return classdef, None
+
def pycall(self, func, args):
if func is None: # consider None as a NULL function pointer
return SomeImpossibleValue()
if isinstance(func, (type, ClassType)) and \
func.__module__ != '__builtin__':
- cls = func
- specialize = getattr(cls, "_specialize_", False)
- if specialize:
- if specialize == "location":
- cls = self.specialize_by_key(cls, self.position_key,
- name="%s__At_%s" % (cls.__name__,
- position_name(self.position_key)))
- else:
- raise Exception, \
- "unsupported specialization type '%s'"%(specialize,)
-
- classdef = self.getclassdef(cls)
+ classdef, s_init = self.get_s_init(func, position=self.position_key)
s_instance = SomeInstance(classdef)
# flow into __init__() if the class has got one
- init = getattr(cls, '__init__', None)
- if init is not None and init != object.__init__:
- # don't record the access of __init__ on the classdef
- # because it is not a dynamic attribute look-up, but
- # merely a static function call
- if hasattr(init, 'im_func'):
- init = init.im_func
- else:
- assert isinstance(init, BuiltinMethodType)
- s_init = self.immutablevalue(init)
- s_init.call(args.prepend(s_instance))
+ if s_init is not None:
+ s_init.call(args.prepend(s_instance), implicit_init=True)
else:
try:
args.fixedunpack(0)
except ValueError:
raise Exception, "no __init__ found in %r" % (cls,)
return s_instance
+
if hasattr(func, '__call__') and \
isinstance(func.__call__, MethodType):
func = func.__call__
Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py (original)
+++ pypy/dist/pypy/annotation/unaryop.py Sat Jun 4 18:28:53 2005
@@ -138,7 +138,7 @@
space = RPythonCallsSpace()
return obj.call(Arguments.fromshape(space, s_shape.const, args_s))
- def call(obj, args):
+ def call(obj, args, implicit_init=False):
#raise Exception, "cannot follow call_args%r" % ((obj, args),)
getbookkeeper().warning("cannot follow call(%r, %r)" % (obj, args))
return SomeObject()
@@ -367,7 +367,7 @@
else:
return bltn.analyser(*args)
- def call(bltn, args):
+ def call(bltn, args, implicit_init=False):
args, kw = args.unpack()
assert not kw, "don't call builtins with keywords arguments"
if bltn.s_self is not None:
@@ -385,9 +385,9 @@
def setattr(pbc, s_attr, s_value):
getbookkeeper().warning("setattr not wanted on %r" % (pbc,))
- def call(pbc, args):
+ def call(pbc, args, implicit_init=False):
bookkeeper = getbookkeeper()
- return bookkeeper.pbc_call(pbc, args)
+ return bookkeeper.pbc_call(pbc, args, implicit_init=implicit_init)
#bookkeeper = getbookkeeper()
#results = []
Modified: pypy/dist/pypy/translator/annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/annrpython.py (original)
+++ pypy/dist/pypy/translator/annrpython.py Sat Jun 4 18:28:53 2005
@@ -169,6 +169,7 @@
print "++-" * 20
raise AnnotatorError('%d blocks are still blocked' %
self.annotated.values().count(False))
+ self.bookkeeper.compute_at_fixpoint()
def binding(self, arg, extquery=False):
"Gives the SomeValue corresponding to the given Variable or Constant."
Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py (original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py Sat Jun 4 18:28:53 2005
@@ -859,6 +859,8 @@
def n(self):
pass
class C(A):
+ def __init__(self):
+ pass
def m(self):
pass
def f(x):
@@ -882,11 +884,12 @@
fc = lambda x: {(None, x): True}
mc = lambda x: {(clsdef(x.im_class), x.im_func): True}
- assert len(callables) == 5
- assert callables == { B: fc(B), C: fc(C),
- A.m.im_func: mc(A.m),
- C.m.im_func: mc(C.m),
- B.n.im_func: mc(B.n) }
+ assert len(callables) == 6
+ assert callables == { B: fc(B), C: fc(C),
+ C.__init__.im_func: fc(C.__init__.im_func),
+ A.m.im_func: mc(A.m),
+ C.m.im_func: mc(C.m),
+ B.n.im_func: mc(B.n) }
ign, repA_m, famA_m = call_families.find((clsdef(A), A.m.im_func))
ign, repC_m, famC_m = call_families.find((clsdef(C), C.m.im_func))
@@ -900,6 +903,9 @@
assert famB_n.patterns == {(0, (), False, False): True }
assert famA_m.patterns == {(0, (), False, False): True }
+
+ ign, repCinit, famCinit = call_families.find((None, C.__init__.im_func))
+ assert famCinit.patterns == {(1, (), False, False): True }
def test_isinstance_usigned(self):
def f(x):
More information about the Pypy-commit
mailing list