[pypy-svn] r51644 - in pypy/branch/gc_hash/pypy/rpython/lltypesystem: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Feb 19 18:14:55 CET 2008
Author: arigo
Date: Tue Feb 19 18:14:55 2008
New Revision: 51644
Modified:
pypy/branch/gc_hash/pypy/rpython/lltypesystem/lltype.py
pypy/branch/gc_hash/pypy/rpython/lltypesystem/test/test_lltype.py
Log:
hash_cache support in lltype for GcStructs, including the
possibility to ask for prebuilt gcstructs to have a specific
hash value.
Modified: pypy/branch/gc_hash/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/gc_hash/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/gc_hash/pypy/rpython/lltypesystem/lltype.py Tue Feb 19 18:14:55 2008
@@ -310,6 +310,24 @@
class GcStruct(RttiStruct):
_gckind = 'gc'
+ _hash_cache = False
+
+ def _install_extras(self, hash_cache=False, **extras):
+ RttiStruct._install_extras(self, **extras)
+ if hash_cache:
+ if self._hash_cache_level() is not None:
+ raise TypeError("in %r, parent structure %r has already got "
+ "a hash_cache" % (self,
+ self._hash_cache_level()))
+ self._hash_cache = True
+
+ def _hash_cache_level(self):
+ TYPE = self
+ while not TYPE._hash_cache:
+ _, TYPE = TYPE._first_struct()
+ if TYPE is None:
+ return None
+ return TYPE
STRUCT_BY_FLAVOR = {'raw': Struct,
'gc': GcStruct}
@@ -1358,8 +1376,10 @@
container = parent
return container
-def _struct_variety(flds, cache={}):
- flds = list(flds)
+def _struct_variety(TYPE, cache={}):
+ flds = list(TYPE._names)
+ if TYPE._hash_cache:
+ flds.append('_hash_cache_')
flds.sort()
tag = tuple(flds)
try:
@@ -1369,11 +1389,6 @@
__slots__ = flds
cache[tag] = _struct1
return _struct1
-
-#for pickling support:
-def _get_empty_instance_of_struct_variety(flds):
- cls = _struct_variety(flds)
- return object.__new__(cls)
class _struct(_parentable):
_kind = "structure"
@@ -1381,7 +1396,7 @@
__slots__ = ()
def __new__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
- my_variety = _struct_variety(TYPE._names)
+ my_variety = _struct_variety(TYPE)
return object.__new__(my_variety)
def __init__(self, TYPE, n=None, initialization=None, parent=None, parentindex=None):
@@ -1825,6 +1840,37 @@
"should have been: %s" % (p, result2, result))
return result
+def _ptr2hashcontainer(p):
+ T = typeOf(p)
+ if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct):
+ raise TypeError, "Ptr(GcStruct) expected, got %r" % (T,)
+ TYPE = T.TO._hash_cache_level()
+ if TYPE is None:
+ raise TypeError, "hash_gc_object: %r has no hash_cache" % (T.TO,)
+ if not p:
+ return None
+ container = cast_pointer(Ptr(TYPE), p)._obj
+ return container
+
+def hash_gc_object(p):
+ container = _ptr2hashcontainer(p)
+ if container is None:
+ return 0 # hash(NULL)
+ try:
+ return container._hash_cache_
+ except AttributeError:
+ result = container._hash_cache_ = intmask(id(container))
+ return result
+
+def init_hash_gc_object(p, value):
+ """For a prebuilt object p, initialize its hash value to 'value'."""
+ container = _ptr2hashcontainer(p)
+ if container is None:
+ raise ValueError("cannot change hash(NULL)!")
+ if hasattr(container, '_hash_cache_'):
+ raise ValueError("the hash of %r was already computed" % (p,))
+ container._hash_cache_ = intmask(value)
+
def isCompatibleType(TYPE1, TYPE2):
return TYPE1._is_compatible(TYPE2)
Modified: pypy/branch/gc_hash/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/branch/gc_hash/pypy/rpython/lltypesystem/test/test_lltype.py (original)
+++ pypy/branch/gc_hash/pypy/rpython/lltypesystem/test/test_lltype.py Tue Feb 19 18:14:55 2008
@@ -727,3 +727,22 @@
setattr(s, word, i)
for i, word in enumerate(words):
assert getattr(s, word) == i
+
+def test_hash_gc_object():
+ S = GcStruct('S', ('x', Signed), hash_cache=False)
+ S2 = GcStruct('S2', ('super', S), hash_cache=True)
+ S3 = GcStruct('S3', ('super', S2))
+ py.test.raises(TypeError, "GcStruct('S4', ('super', S3), hash_cache=True)")
+
+ s3 = malloc(S3)
+ hash3 = hash_gc_object(s3)
+ assert hash3 == hash_gc_object(s3)
+ assert hash3 == hash_gc_object(s3.super)
+ py.test.raises(TypeError, hash_gc_object, s3.super.super)
+ py.test.raises(ValueError, init_hash_gc_object, s3, -123)
+
+ s3 = malloc(S3)
+ init_hash_gc_object(s3, -123)
+ assert -123 == hash_gc_object(s3)
+ assert -123 == hash_gc_object(s3.super)
+ py.test.raises(TypeError, hash_gc_object, s3.super.super)
More information about the Pypy-commit
mailing list