[pypy-svn] r54600 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem test

arigo at codespeak.net arigo at codespeak.net
Fri May 9 18:27:24 CEST 2008


Author: arigo
Date: Fri May  9 18:27:23 2008
New Revision: 54600

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/rclass.py
   pypy/dist/pypy/rpython/test/test_rclass.py
Log:
Another circularity bug in the rtyper that was here forever
but never triggered so far, involving a cycle like
"dictionary -> RPython instance as a key -> dictionary".


Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri May  9 18:27:23 2008
@@ -408,17 +408,16 @@
         else:
             return self.rbase.get_ll_hash_function()
 
-    def initialize_prebuilt_instance(self, value, classdef, result):
+    def initialize_prebuilt_data(self, value, classdef, result):
         if self.classdef is not None:
             # recursively build the parent part of the instance
-            self.rbase.initialize_prebuilt_instance(value, classdef,
-                                                    result.super)
+            self.rbase.initialize_prebuilt_data(value, classdef, result.super)
             # then add instance attributes from this level
             for name, (mangled_name, r) in self.fields.items():
                 if r.lowleveltype is Void:
                     llattrvalue = None
                 elif name == '_hash_cache_': # hash() support
-                    llattrvalue = hash(value)
+                    continue   # already done by initialize_prebuilt_hash()
                 else:
                     try:
                         attrvalue = getattr(value, name)
@@ -438,6 +437,14 @@
             rclass = getclassrepr(self.rtyper, classdef)
             result.typeptr = rclass.getvtable()
 
+    def initialize_prebuilt_hash(self, value, result):
+        if self.classdef is not None:
+            self.rbase.initialize_prebuilt_hash(value, result.super)
+            if '_hash_cache_' in self.fields:
+                mangled_name, r = self.fields['_hash_cache_']
+                llattrvalue = hash(value)
+                setattr(result, mangled_name, llattrvalue)
+
     def getfieldrepr(self, attr):
         """Return the repr used for the given attribute."""
         if attr in self.fields:

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Fri May  9 18:27:23 2008
@@ -471,7 +471,7 @@
                   resulttype=ootype.Void)
         return v_instance
         
-    def initialize_prebuilt_instance(self, value, classdef, result):
+    def initialize_prebuilt_data(self, value, classdef, result):
         # then add instance attributes from this level
         classrepr = getclassrepr(self.rtyper, self.classdef)
         for mangled, (oot, default) in self.lowleveltype._allfields().items():
@@ -480,7 +480,7 @@
             elif mangled == 'meta':
                 llattrvalue = classrepr.get_meta_instance()
             elif mangled == '_hash_cache_': # hash() support
-                llattrvalue = hash(value)
+                continue   # already done by initialize_prebuilt_hash()
             else:
                 name = unmangle(mangled, self.rtyper.getconfig())
                 try:
@@ -496,6 +496,10 @@
                     llattrvalue = self.allfields[mangled].convert_const(attrvalue)
             setattr(result, mangled, llattrvalue)
 
+    def initialize_prebuilt_hash(self, value, result):
+        if '_hash_cache_' in self.lowleveltype._allfields():
+            result._hash_cache_ = hash(value)
+
 buildinstancerepr = InstanceRepr
 
 

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Fri May  9 18:27:23 2008
@@ -167,6 +167,12 @@
             self.initialize_prebuilt_instance(Ellipsis, self.classdef, result)
             return result
 
+    def initialize_prebuilt_instance(self, value, classdef, result):
+        # must fill in the _hash_cache_ field before the other ones
+        # (see test_circular_hash_initialization)
+        self.initialize_prebuilt_hash(value, result)
+        self.initialize_prebuilt_data(value, classdef, result)
+
     def rtype_type(self, hop):
         raise NotImplementedError
 

Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py	Fri May  9 18:27:23 2008
@@ -412,7 +412,21 @@
         # relevant on top of the ootypesystem though.
         assert res.item2 == hash(c)
         assert res.item3 == hash(d)
-        
+
+    def test_circular_hash_initialization(self):
+        class B:
+            pass
+        class C(B):
+            pass
+        c1 = C()
+        c1.somedict = {c1: True, C(): False}
+        def f():
+            B().somedict = {}      # force the attribute up
+            c1.somedict[c1] = 123
+            return len(c1.somedict)
+        res = self.interpret(f, [])
+        assert res == 2
+
     def test_type(self):
         class A:
             pass



More information about the Pypy-commit mailing list