Author: Lars Wassermann <[email protected]>
Branch: 
Changeset: r163:d8785e33876b
Date: 2013-03-11 01:31 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/d8785e33876b/

Log:    added version updates when superclass changes still missing are
        the appropriate annotations, weak ref instead of set() to subclasses

diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -293,10 +293,12 @@
     # XXX
     s = instantiate(shadow.ClassShadow)
     s.space = space
+    s.version = shadow.Version()
     s._w_self = w_class
+    s.subclass_s = set()
+    s._s_superclass = None
     s.store_w_superclass(w_superclass)
     s.name = name
-    s.version = shadow.Version()
     s.instance_size = instsize
     s.instance_kind = format
     s._s_methoddict = None
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -49,6 +49,9 @@
         AbstractShadow.store(self, n0, w_value)
         self.update()
 
+    def change(self):
+        self.version = Version()
+
 class Version:
     pass
 # ____________________________________________________________ 
@@ -71,11 +74,14 @@
     (i.e. used as the class of another Smalltalk object).
     """
 
-    _attr_ = ["name", "instance_size", "instance_varsized", "instance_kind", 
"_s_methoddict", "_s_superclass"]
+    _attr_ = ["name", "instance_size", "instance_varsized", "instance_kind",
+                "_s_methoddict", "_s_superclass", "subclass_s"]
 
     def __init__(self, space, w_self):
         # fields added here should also be in objspace.py:56ff, 300ff
         self.name = ''
+        self._s_superclass = None
+        self.subclass_s = set()
         AbstractCachingShadow.__init__(self, space, w_self)
 
     def getname(self):
@@ -143,8 +149,8 @@
             self._s_superclass = None
         else:
             assert isinstance(w_superclass, model.W_PointersObject)
-            self._s_superclass = w_superclass.as_class_get_shadow(self.space)
-        self.version = Version()
+            self.store_w_superclass(w_superclass)
+        self.changed()
 
     def guess_class_name(self):
         if self.name != '':
@@ -173,7 +179,7 @@
             self.name = w_name.as_string()
         else:
             self.name = None
-        self.version = Version()
+        self.changed()
 
     def new(self, extrasize=0):
         w_cls = self.w_self()
@@ -232,7 +238,27 @@
         if w_class is None:
             self._s_superclass = None
         else:
-            self._s_superclass = w_class.as_class_get_shadow(self.space)
+            s_scls = w_class.as_class_get_shadow(self.space)
+            if self._s_superclass is s_scls: 
+                return
+            elif (self._s_superclass is not None 
+                and self._s_superclass is not s_scls):
+                self._s_superclass.detach_s_class(self)
+            self._s_superclass = s_scls
+            self._s_superclass.attach_s_class(self)
+
+    def attach_s_class(self, s_other): self.subclass_s.add(s_other)
+    def detach_s_class(self, s_other): self.subclass_s.remove(s_other)
+
+    def changed(self):
+        self.superclass_changed(Version())
+
+    # this is done, because the class-hierarchy contains cycles
+    def superclass_changed(self, version):
+        if self.version is not version:
+            self.version = version
+            for s_class in self.subclass_s:
+                s_class.superclass_changed(version)
 
     # _______________________________________________________________
     # Methods for querying the format word, taken from the blue book:
@@ -340,7 +366,7 @@
                 selector = w_selector.as_string()
                 w_compiledmethod._likely_methodname = selector
         if self.s_class:
-            self.s_class.version = Version()
+            self.s_class.changed()
         self.invalid = False
 
 
@@ -975,8 +1001,7 @@
         self.version = Version()
         return self._w_self._store(n0, w_value)
 
-    def update(self):
-        self.version = Version()
+    def update(self): pass
 
 class ObserveeShadow(AbstractShadow):
     _attr_ = ['dependent']
diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py
--- a/spyvm/test/test_shadow.py
+++ b/spyvm/test/test_shadow.py
@@ -252,4 +252,25 @@
     w_array.atput0(space, i, baz)
 
     assert s_class.lookup(key) is baz.as_compiledmethod_get_shadow(space)
-    assert version is not s_class.version
\ No newline at end of file
+    assert version is not s_class.version
+
+def test_updating_class_changes_subclasses():
+    w_parent = build_smalltalk_class("Demo", 0x90,
+            methods={'bar': model.W_CompiledMethod(0)})
+    w_class = build_smalltalk_class("Demo", 0x90,
+            methods={'foo': model.W_CompiledMethod(0)}, w_superclass=w_parent)
+    s_class = w_class.as_class_get_shadow(space)
+    version = s_class.version
+
+    w_method = model.W_CompiledMethod(0)
+    key = space.wrap_string('foo')
+
+    s_md = w_parent.as_class_get_shadow(space).s_methoddict()
+    s_md.sync_cache()
+    w_ary = s_md._w_self._fetch(constants.METHODDICT_VALUES_INDEX)
+    s_md._w_self.atput0(space, 0, key)
+    w_ary.atput0(space, 0, w_method)
+
+    assert s_class.lookup(key) is w_method.as_compiledmethod_get_shadow(space)
+    assert s_class.version is not version
+    assert s_class.version is w_parent.as_class_get_shadow(space).version
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to