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