[pypy-svn] r17813 - in pypy/dist/pypy: rpython rpython/test translator
arigo at codespeak.net
arigo at codespeak.net
Sat Sep 24 11:57:03 CEST 2005
Author: arigo
Date: Sat Sep 24 11:56:57 2005
New Revision: 17813
Modified:
pypy/dist/pypy/rpython/lltype.py
pypy/dist/pypy/rpython/test/test_lltype.py
pypy/dist/pypy/translator/transform.py
Log:
Optimizations of translate_pypy, motivated by a profiled run which
you can see at the end of /tmp/PROFILE-out on the snake server:
* LowLevelType.__hash__ is called 99 million times. Let's make it
cache its result as best as possible.
* transform.checkgraphs() calls checkgraph() too many times --
each graph was fully rechecked the same number of times as the
number of blocks it contains.
Modified: pypy/dist/pypy/rpython/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltype.py Sat Sep 24 11:56:57 2005
@@ -35,6 +35,10 @@
class LowLevelType(object):
+ # the following line prevents '__cached_hash' to be in the __dict__ of
+ # the instance, which is needed for __eq__() and __hash__() to work.
+ __slots__ = ['__dict__', '__cached_hash']
+
def __eq__(self, other):
return self.__class__ is other.__class__ and (
self is other or safe_equal(self.__dict__, other.__dict__))
@@ -44,20 +48,28 @@
def __hash__(self):
# cannot use saferecursive() -- see test_lltype.test_hash().
- # this version uses a compromize between computation time and
- # collision-avoidance that can be customized if needed.
+ # NB. the __cached_hash should neither be used nor updated
+ # if we enter with hash_level > 0, because the computed
+ # __hash__ can be different in this situation.
+ hash_level = 0
try:
- if TLS.nested_hash_level >= 3:
- return 0
+ hash_level = TLS.nested_hash_level
+ if hash_level == 0:
+ return self.__cached_hash
except AttributeError:
- TLS.nested_hash_level = 0
+ pass
+ if hash_level >= 3:
+ return 0
items = self.__dict__.items()
items.sort()
- TLS.nested_hash_level += 1
+ TLS.nested_hash_level = hash_level + 1
try:
- return hash((self.__class__,) + tuple(items))
+ result = hash((self.__class__,) + tuple(items))
finally:
- TLS.nested_hash_level -= 1
+ TLS.nested_hash_level = hash_level
+ if hash_level == 0:
+ self.__cached_hash = result
+ return result
# due to this dynamic hash value, we should forbid
# pickling, until we have an algorithm for that.
Modified: pypy/dist/pypy/rpython/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_lltype.py (original)
+++ pypy/dist/pypy/rpython/test/test_lltype.py Sat Sep 24 11:56:57 2005
@@ -305,6 +305,7 @@
S = ForwardReference()
S.become(Struct('S', ('p', Ptr(S))))
assert S == S
+ hash(S) # assert no crash, and force the __cached_hash computation
S1 = Struct('S', ('p', Ptr(S)))
assert S1 == S
assert S == S1
Modified: pypy/dist/pypy/translator/transform.py
==============================================================================
--- pypy/dist/pypy/translator/transform.py (original)
+++ pypy/dist/pypy/translator/transform.py Sat Sep 24 11:56:57 2005
@@ -17,10 +17,13 @@
def checkgraphs(self, blocks):
+ seen = {}
for block in blocks:
fn = self.annotated[block]
graph = self.translator.flowgraphs[fn]
- checkgraph(graph)
+ if graph not in seen:
+ checkgraph(graph)
+ seen[graph] = True
def fully_annotated_blocks(self):
"""Ignore blocked blocks."""
More information about the Pypy-commit
mailing list