Author: Anton Gulenko <[email protected]>
Branch: storage
Changeset: r693:d5b590bdaa03
Date: 2014-03-24 16:38 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/d5b590bdaa03/

Log:    Working on merging strategies and shadows.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -93,6 +93,7 @@
         raise NotImplementedError()
 
     def fillin(self, space, g_self):
+        import pdb; pdb.set_trace()
         raise NotImplementedError()
 
     def getword(self, n0):
@@ -157,6 +158,10 @@
     def __init__(self, value):
         self.value = intmask(value)
 
+    def fillin(self, space, g_obj):
+        # Is created directly with the correct value.
+        pass
+        
     def getclass(self, space):
         return space.w_SmallInteger
 
@@ -443,7 +448,10 @@
 
     def as_embellished_string(self, className, additionalInformation):
         from rpython.rlib.objectmodel import current_object_addr_as_int
-        name = self.shadow_of_my_class(self.space).name or "?"
+        if self.s_class and self.s_class.name:
+            name = self.s_class.name
+        else:
+            name = "?"
         return "<%s (a %s) %s>" % (className, name,
                 #hex(current_object_addr_as_int(self)),
                 additionalInformation)
@@ -483,13 +491,41 @@
     def __init__(self, space, w_class, size):
         """Create new object with size = fixed + variable size."""
         W_AbstractObjectWithClassReference.__init__(self, space, w_class)
-        self.store_shadow(None)
+        self.initialize_storage(space, size)
 
+    def initialize_storage(self, space, size):
+        if not self.shadow:
+            self.store_shadow(self.default_storage(space, size))
+        else:
+            self.shadow.initialize_storage(space, size)
+        
     def fillin(self, space, g_self):
         self.s_class = g_self.get_class().as_class_get_penumbra(space)
         self.hash = g_self.get_hash()
         self.space = space
-
+        for g_obj in g_self.get_g_pointers():
+            g_obj.fillin(space)
+        pointers = g_self.get_pointers()
+        self.initialize_storage(space, len(pointers))
+        self.store_all(space, pointers)
+        
+    def fetch_all(self, space):
+        return [self.fetch(space, i) for i in range(self.size())]
+    
+    def store_all(self, space, collection):
+        # Be tolerant: copy over as many elements as possible, set rest to nil.
+        # The size of the object cannot be changed in any case.
+        # This should only by used in tests/debugging.
+        my_length = self.size()
+        incoming_length = min(my_length, len(collection))
+        i = 0
+        while i < incoming_length:
+            self.store(space, i, collection[i])
+            i = i+1
+        while i < my_length:
+            self.store(space, i, w_nil)
+            i = i+1
+        
     def at0(self, space, index0):
         # To test, at0 = in varsize part
         return self.fetch(space, index0+self.instsize(space))
@@ -499,14 +535,10 @@
         self.store(space, index0 + self.instsize(space), w_value)
 
     def fetch(self, space, n0):
-        if self.has_shadow():
-            return self._get_shadow().fetch(n0)
-        return self._fetch(space, n0)
+        return self._get_shadow().fetch(n0)
 
     def store(self, space, n0, w_value):
-        if self.has_shadow():
-            return self._get_shadow().store(n0, w_value)
-        return self._store(space, n0, w_value)
+        return self._get_shadow().store(n0, w_value)
 
     def varsize(self, space):
         return self.size() - self.instsize(space)
@@ -518,32 +550,25 @@
         return self.varsize(space)
 
     def size(self):
-        if self.has_shadow():
-            return self._get_shadow().size()
-        return self.basic_size()
+        return self._get_shadow().size()
 
     def store_shadow(self, shadow):
-        assert self.shadow is None or self.shadow is shadow
+        #assert self.shadow is None or self.shadow is shadow
         self.shadow = shadow
 
     def _get_shadow(self):
         return self.shadow
     
     @objectmodel.specialize.arg(2)
-    def attach_shadow_of_class(self, space, TheClass):
-        shadow = TheClass(space, self)
-        self.store_shadow(shadow)
-        shadow.attach_shadow()
-        return shadow
-
-    @objectmodel.specialize.arg(2)
     def as_special_get_shadow(self, space, TheClass):
-        shadow = self._get_shadow()
-        if not isinstance(shadow, TheClass):
-            if shadow is not None:
-                raise DetachingShadowError(shadow, TheClass)
-            shadow = self.attach_shadow_of_class(space, TheClass)
-            shadow.update()
+        old_shadow = self._get_shadow()
+        shadow = old_shadow
+        if not isinstance(old_shadow, TheClass):
+            shadow = TheClass(space, self)
+            if old_shadow is not None:
+                shadow.copy_from(old_shadow)
+            self.store_shadow(shadow)
+            shadow.attach_shadow()
         return shadow
 
     def get_shadow(self, space):
@@ -558,11 +583,11 @@
     def as_class_get_penumbra(self, space):
         from spyvm.shadow import ClassShadow
         s_class = self._get_shadow()
-        if s_class is None:
+        if s_class is None or not isinstance(s_class, ClassShadow):
             s_class = ClassShadow(space, self)
+            if self.shadow is not None:
+                s_class.copy_from(self.shadow)
             self.store_shadow(s_class)
-        else:
-            assert isinstance(s_class, ClassShadow)
         return s_class
 
     def as_blockcontext_get_shadow(self, space):
@@ -600,201 +625,40 @@
     def become(self, w_other):
         if not isinstance(w_other, W_AbstractPointersObject):
             return False
+        self.strategy, w_other.strategy = w_other.strategy, self.strategy
+        self._size, w_other._size = w_other._size, self._size
+        self.list_storage, w_other.list_storage = w_other.list_storage, 
self.list_storage
+        self.int_storage, w_other.int_storage = w_other.int_storage, 
self.int_storage
+        
         # switching means also switching shadows
         self.shadow, w_other.shadow = w_other.shadow, self.shadow
         # shadow links are in both directions -> also update shadows
         if    self.shadow is not None:    self.shadow._w_self = self
         if w_other.shadow is not None: w_other.shadow._w_self = w_other
         W_AbstractObjectWithClassReference._become(self, w_other)
-        return True
 
+    @jit.unroll_safe
+    def clone(self, space):
+        my_pointers = self.fetch_all(space)
+        w_result = W_PointersObject(self.space, self.getclass(space), 
len(my_pointers))
+        w_result.fillin_pointers(space, my_pointers)
+        return w_result
+        
     @jit.elidable
     def as_repr_string(self):
         return W_AbstractObjectWithClassReference.as_embellished_string(self,
                                 className='W_PointersObject',
                                 additionalInformation='len=%d' % self.size())
 
-class StatsSorter(TimSort):
-    def lt(self, a, b):
-        if a[0] == b[0]:
-            if a[1] == b[1]:
-                return a[2] < b[2]
-            else:
-                return a[1] < b[1]
-        else:
-            return a[0] < b[0]
-
-class StrategyStatistics(object):
-    # Key: (operation_name, old_strategy, new_strategy)
-    # Value: [sizes]
-    stats = {}
-    do_log = False
-    do_stats = False
-    do_stats_sizes = False
-    
-    def stat_operation(self, operation_name, old_strategy, new_strategy, size):
-        key = (operation_name, old_strategy, new_strategy)
-        if not key in self.stats:
-            self.stats[key] = []
-        self.stats[key].append(size)
-    def log_operation(self, op, new_strategy_tag, old_strategy_tag, classname, 
size):
-        print "%s (%s, was %s) of %s size %d" % (op, new_strategy_tag, 
old_strategy_tag, classname, size)
-    def sorted_keys(self):
-        keys = [ x for x in self.stats ]
-        StatsSorter(keys).sort()
-        return keys
-    def print_stats(self):
-        for key in self.sorted_keys():
-            sizes = self.stats[key]
-            sum = 0
-            for s in sizes:
-                sum += s
-            print "%s: %d times, avg size: %d" % (key, len(sizes), 
sum/len(sizes))
-            if self.do_stats_sizes:
-                print "       All sizes: %s" % sizes
-strategy_stats = StrategyStatistics()
-
 class W_PointersObject(W_AbstractPointersObject):
-    _attrs_ = ['_size', 'list_storage', 'int_storage', 'strategy']
-    if not we_are_translated():
-        list_storage = None
-        int_storage = None
-    
-    @jit.unroll_safe
-    def __init__(self, space, w_class, size):
-        from spyvm.strategies import empty_strategy
-        """Create new object with size = fixed + variable size."""
-        W_AbstractPointersObject.__init__(self, space, w_class, size)
-        self.strategy = empty_strategy(self.s_class)
-        self.initialize_storage(space, size)
-        self.log_strategy_operation("Initialized")
-    
-    def log_strategy_operation(self, op, old_strategy=None):
-        if strategy_stats.do_log or strategy_stats.do_stats:
-            classname = "<unknown>"
-            if self.has_class():
-                classname = self.s_class.name
-            size = self.basic_size()
-            new_strategy_tag = self.strategy.strategy_tag
-            old_strategy_tag = "None"
-            if old_strategy is not None:
-                old_strategy_tag = old_strategy.strategy_tag
-            if strategy_stats.do_stats:
-                strategy_stats.stat_operation(op, old_strategy_tag, 
new_strategy_tag, size)
-            if strategy_stats.do_log:
-                strategy_stats.log_operation(op, new_strategy_tag, 
old_strategy_tag, classname, size)
-    
-    def initialize_storage(self, space, size):
-        self._size = size
-        self.strategy.set_initial_storage(space, self, size)
-    
-    def fillin_pointers(self, space, collection):
-        from spyvm.strategies import strategy_for_list
-        self.strategy = strategy_for_list(self.s_class, collection)
-        self._size = len(collection)
-        self.strategy.set_storage_for_list(space, self, collection)
-    
-    def fillin(self, space, g_self):
-        W_AbstractPointersObject.fillin(self, space, g_self)
-        self.fillin_pointers(space, g_self.get_pointers())
-        self.log_strategy_operation("Filled in")
-
-    def switch_strategy(self, space, new_strategy):
-        assert self.strategy != new_strategy
-        new_strategy.set_storage_copied_from(space, self, self, 
reuse_storage=True)
-        old_strategy = self.strategy
-        self.strategy = new_strategy
-        self.log_strategy_operation("Switched", old_strategy)
-
-    def store_with_new_strategy(self, space, new_strategy, n0, w_val):
-        self.switch_strategy(space, new_strategy)
-        return self.store(space, n0, w_val)
-    
-    def fetch_all(self, space):
-        return [self.fetch(space, i) for i in range(self.size())]
-    
-    def store_all(self, space, collection):
-        # Be tolerant: copy over as many elements as possible, set rest to nil.
-        # The size of the object cannot be changed in any case.
-        # This should only by used in tests/debugging.
-        my_length = self.size()
-        incoming_length = min(my_length, len(collection))
-        i = 0
-        while i < incoming_length:
-            self.store(space, i, collection[i])
-            i = i+1
-        while i < my_length:
-            self.store(space, i, w_nil)
-            i = i+1
-    
-    def _fetch(self, space, n0):
-        return self.strategy.fetch(space, self, n0)
-
-    def _store(self, space, n0, w_value):
-        return self.strategy.store(space, self, n0, w_value)
-
-    def basic_size(self):
-        return self._size
-
-    def become(self, w_other):
-        if not isinstance(w_other, W_PointersObject):
-            return False
-        self.strategy, w_other.strategy = w_other.strategy, self.strategy
-        self._size, w_other._size = w_other._size, self._size
-        self.list_storage, w_other.list_storage = w_other.list_storage, 
self.list_storage
-        self.int_storage, w_other.int_storage = w_other.int_storage, 
self.int_storage
-        return W_AbstractPointersObject.become(self, w_other)
-
-    @jit.unroll_safe
-    def clone(self, space):
-        my_pointers = self.fetch_all(space)
-        w_result = W_PointersObject(self.space, self.getclass(space), 
len(my_pointers))
-        w_result.fillin_pointers(space, my_pointers)
-        self.log_strategy_operation("Cloned")
-        return w_result
+    def default_storage(self, space, size):
+        from spyvm.shadow import ListStorageShadow
+        return ListStorageShadow(space, self, size)
 
 class W_WeakPointersObject(W_AbstractPointersObject):
-    _attrs_ = ['_weakvars']
-    
-    @jit.unroll_safe
-    def __init__(self, space, w_class, size):
-        W_AbstractPointersObject.__init__(self, space, w_class, size)
-        self._weakvars = [weakref.ref(w_nil)] * size
-
-    def fillin(self, space, g_self):
-        raise NotImplementedError("we don't expect weak objects in a fresh 
image")
-
-    def _fetch(self, space, n0):
-        weakobj = self._weakvars[n0]
-        return weakobj() or w_nil
-
-    def _store(self, space, n0, w_value):
-        assert w_value is not None
-        self._weakvars[n0] = weakref.ref(w_value)
-
-    def basic_size(self):
-        return len(self._weakvars)
-
-    def invariant(self):
-        return (W_AbstractObjectWithClassReference.invariant(self) and
-                isinstance(self._weakvars, list))
-
-    def become(self, w_other):
-        if not isinstance(w_other, W_WeakPointersObject):
-            return False
-        self._weakvars, w_other._weakvars = w_other._weakvars, self._weakvars
-        return W_AbstractPointersObject.become(self, w_other)
-
-    @jit.unroll_safe
-    def clone(self, space):
-        w_result = W_WeakPointersObject(self.space, self.getclass(space),
-                                        len(self._weakvars))
-        for i, var in enumerate(self._weakvars):
-            w_obj = var()
-            if w_obj is None:
-                w_obj = w_nil
-            w_result._weakvars[i] = weakref.ref(w_obj)
-        return w_result
+    def default_storage(self, space, size):
+        from spyvm.shadow import WeakListStorageShadow
+        return WeakListStorageShadow(space, self, size)
 
 class W_BytesObject(W_AbstractObjectWithClassReference):
     _attrs_ = ['bytes', 'c_bytes', '_size']
@@ -1272,7 +1136,7 @@
                     if not w_candidate.strategy.needs_objspace:
                         # We can fetch without having an object space at hand.
                         # XXX How to get an object space from a 
CompiledMethodShadow, anyways?
-                        w_class = w_candidate._fetch(None, 1)
+                        w_class = w_candidate.fetch(None, 1)
                         if isinstance(w_class, W_PointersObject):
                             d_shadow = w_class._get_shadow()
                             if isinstance(d_shadow, shadow.ClassShadow):
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -107,38 +107,35 @@
                                          name=cls_nm[2:])
 
         define_cls("w_Magnitude", "w_Object")
-        define_cls("w_Character", "w_Magnitude", instvarsize=1)
+            define_cls("w_Character", "w_Magnitude", instvarsize=1)
         define_cls("w_Number", "w_Magnitude")
         define_cls("w_Integer", "w_Number")
-        define_cls("w_SmallInteger", "w_Integer")
-        define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES)
-        define_cls("w_Float", "w_Number", format=shadow.BYTES)
-        define_cls("w_Message", "w_Object")
+            define_cls("w_SmallInteger", "w_Integer")
+            define_cls("w_LargePositiveInteger", "w_Integer", 
format=shadow.BYTES)
+            define_cls("w_Float", "w_Number", format=shadow.BYTES)
+            define_cls("w_Message", "w_Object")
         define_cls("w_Collection", "w_Object")
         define_cls("w_SequenceableCollection", "w_Collection")
         define_cls("w_ArrayedCollection", "w_SequenceableCollection")
-        define_cls("w_Array", "w_ArrayedCollection", varsized=True)
-        define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES)
-        define_cls("w_Bitmap", "w_ArrayedCollection", varsized=True, 
format=shadow.WORDS)
+            define_cls("w_Array", "w_ArrayedCollection", varsized=True)
+            define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES)
+            define_cls("w_Bitmap", "w_ArrayedCollection", varsized=True, 
format=shadow.WORDS)
         define_cls("w_UndefinedObject", "w_Object")
         define_cls("w_Boolean", "w_Object")
         define_cls("w_True", "w_Boolean")
         define_cls("w_False", "w_Boolean")
-        define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES)
+            define_cls("w_ByteArray", "w_ArrayedCollection", 
format=shadow.BYTES)
         define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True)
-        define_cls("w_CompiledMethod", "w_ByteArray", 
format=shadow.COMPILED_METHOD)
+            define_cls("w_CompiledMethod", "w_ByteArray", 
format=shadow.COMPILED_METHOD)
         define_cls("w_ContextPart", "w_Object")
-        define_cls("w_MethodContext", "w_ContextPart")
+            define_cls("w_MethodContext", "w_ContextPart")
         define_cls("w_Link", "w_Object")
-        define_cls("w_Process", "w_Link")
-        define_cls("w_Point", "w_Object")
+            define_cls("w_Process", "w_Link")
+            define_cls("w_Point", "w_Object")
         define_cls("w_LinkedList", "w_SequenceableCollection")
-        define_cls("w_Semaphore", "w_LinkedList")
-        define_cls("w_BlockContext", "w_ContextPart",
-                   instvarsize=constants.BLKCTX_STACK_START)
-        define_cls("w_BlockClosure", "w_Object",
-                   instvarsize=constants.BLKCLSR_SIZE,
-                   varsized=True)
+            define_cls("w_Semaphore", "w_LinkedList")
+            define_cls("w_BlockContext", "w_ContextPart", 
instvarsize=constants.BLKCTX_STACK_START)
+            define_cls("w_BlockClosure", "w_Object", 
instvarsize=constants.BLKCLSR_SIZE, varsized=True)
         # make better accessors for classes that can be found in special object
         # table
         for name in constants.classes_in_special_object_table.keys():
@@ -162,9 +159,7 @@
         # initialize their fields to nil, we have to create it in the model
         # package, and then patch up its fields here:
         def patch_nil(w_nil):
-            from spyvm.strategies import ListStorageStrategy
             w_nil.space = self
-            w_nil.strategy = ListStorageStrategy.singleton
             w_nil.initialize_storage(self, 0)
             w_nil.s_class = 
self.classtable['w_UndefinedObject'].as_class_get_penumbra(self)
             return w_nil
@@ -336,6 +331,7 @@
                                              # a dummy placeholder for testing
     # XXX
     s = instantiate(shadow.ClassShadow)
+    s.storage = []
     s.space = space
     s.version = version.Version()
     s._w_self = w_class
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -910,7 +910,7 @@
     w_class = s_cm.w_compiledin
     if w_class:
         assert isinstance(w_class, model.W_PointersObject)
-        w_class.as_class_get_shadow(interp.space).flush_caches()
+        w_class.as_class_get_shadow(interp.space).flush_method_caches()
     return w_rcvr
 
 
@@ -1437,7 +1437,7 @@
     if not isinstance(w_rcvr, model.W_PointersObject):
         raise PrimitiveFailedError()
     s_class = w_rcvr.as_class_get_shadow(interp.space)
-    s_class.flush_caches()
+    s_class.flush_method_caches()
     return w_rcvr
 
 # ___________________________________________________________________________
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -16,45 +16,74 @@
         self.space = space
         self._w_self = w_self
     def fetch(self, n0):
-        return self.w_self()._fetch(self.space, n0)
+        import pdb; pdb.set_trace()
+        raise NotImplementedError("Abstract class")
     def store(self, n0, w_value):
-        return self.w_self()._store(self.space, n0, w_value)
+        import pdb; pdb.set_trace()
+        raise NotImplementedError("Abstract class")
     def size(self):
-        return self.w_self().basic_size()
+        import pdb; pdb.set_trace()
+        raise NotImplementedError("Abstract class")
     def w_self(self):
         return self._w_self
     def getname(self):
         return repr(self)
     def attach_shadow(self): pass
-    def update(self): pass
+    
+    def initialize_storage(self, space, size):
+        pass
+    
+    def copy_from(self, other_shadow):
+        assert self.size() == other_shadow.size()
+        for i in range(self.size()):
+            self.store(i, other_shadow.fetch(i))
 
-class AbstractCachingShadow(AbstractShadow):
+class ListStorageShadow(AbstractShadow):
+    _attrs_ = ['storage']
+    
+    def __init__(self, space, w_self, size):
+        AbstractShadow.__init__(self, space, w_self)
+        self.initialize_storage(space, size)
+    
+    def initialize_storage(self, space, size):
+        self.storage = [model.w_nil] * size
+    def fetch(self, n0):
+        return self.storage[n0]
+    def store(self, n0, w_value):
+        self.storage[n0] = w_value
+    def size(self):
+        return len(self.storage)
+    def copy_from(self, other_shadow):
+        if self.size() != other_shadow.size():
+            self.initialize_storage(other_shadow.space, other_shadow.size())
+        AbstractShadow.copy_from(self, other_shadow)
+
+class WeakListStorageShadow(AbstractShadow):
+    _attrs_ = ['storage']
+    
+    def __init__(self, space, w_self, size):
+        AbstractShadow.__init__(self, space, w_self)
+        self.storage = [weakref.ref(w_nil)] * size
+    
+    def fetch(self, n0):
+        weakobj = self.storage[n0]
+        return weakobj() or w_nil
+    def store(self, n0, w_value):
+        assert w_value is not None
+        self.storage[n0] = weakref.ref(w_value)
+    def size(self):
+        return len(self.storage)
+    
+class AbstractCachingShadow(ListStorageShadow):
     _immutable_fields_ = ['version?']
     _attrs_ = ['version']
     import_from_mixin(version.VersionMixin)
-
     version = None
     
     def __init__(self, space, w_self):
-        AbstractShadow.__init__(self, space, w_self)
+        ListStorageShadow.__init__(self, space, w_self, 0)
         self.changed()
 
-    def attach_shadow(self):
-        self.w_self().store_shadow(self)
-        self.update()
-
-    def update(self):
-        """This should get called whenever the base Smalltalk
-        object changes."""
-        self.sync_cache()
-
-    def sync_cache(self):
-        raise NotImplementedError()
-
-    def store(self, n0, w_value):
-        AbstractShadow.store(self, n0, w_value)
-        self.update()
-
 # ____________________________________________________________
 
 POINTERS = 0
@@ -78,6 +107,7 @@
 
     _attrs_ = ["name", "_instance_size", "instance_varsized", "instance_kind",
                 "_s_methoddict", "_s_superclass", "subclass_s"]
+    name = None
     
     def __init__(self, space, w_self):
         # fields added here should also be in objspace.py:56ff, 300ff
@@ -86,21 +116,26 @@
         self.subclass_s = {}
         AbstractCachingShadow.__init__(self, space, w_self)
 
-    def getname(self):
-        return "%s class" % (self.name or '?',)
-
-    def sync_cache(self):
-        from spyvm.objspace import UnwrappingError
-        "Update the ClassShadow with data from the w_self class."
-
-        w_self = self.w_self()
-        if w_self.size() == 0:
-            return
-
-        # read and painfully decode the format
-        try:
-            classformat = self.space.unwrap_int(
-                w_self._fetch(self.space, constants.CLASS_FORMAT_INDEX))
+    def copy_from(self, other_storage):
+        AbstractCachingShadow.copy_from(self, other_storage)
+        if not self._s_methoddict:
+            import pdb; pdb.set_trace()
+        
+    def store(self, n0, w_val):
+        if self.name == "String":
+            import pdb; pdb.set_trace()
+        
+        AbstractCachingShadow.store(self, n0, w_val)
+        if n0 == constants.CLASS_SUPERCLASS_INDEX:
+            self.store_w_superclass(w_val)
+        elif n0 == constants.CLASS_METHODDICT_INDEX:
+            assert isinstance(w_val, model.W_PointersObject)
+            if not w_val.is_same_object(self.space.w_nil):
+                self._s_methoddict = w_val.as_methoddict_get_shadow(self.space)
+                self._s_methoddict.s_class = self
+        elif n0 == constants.CLASS_FORMAT_INDEX:
+            # read and painfully decode the format
+            classformat = self.space.unwrap_int(w_val)
             # The classformat in Squeak, as an integer value, is:
             #    <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec>
             #                                    <6 bits=instSize\\64><1 bit=0>
@@ -139,44 +174,9 @@
                 self.instance_kind = COMPILED_METHOD
             else:
                 raise ClassShadowError("unknown format %d" % (format,))
-        except UnwrappingError:
-            assert w_self._fetch(self.space, constants.CLASS_FORMAT_INDEX) is 
self.space.w_nil
-            pass # not enough information stored in w_self, yet
-
-        self.guess_class_name()
-
-        # read the methoddict
-        w_methoddict = w_self._fetch(self.space, 
constants.CLASS_METHODDICT_INDEX)
-        assert isinstance(w_methoddict, model.W_PointersObject)
-        if not w_methoddict.is_same_object(self.space.w_nil):
-            self._s_methoddict = 
w_methoddict.as_methoddict_get_shadow(self.space)
-            self._s_methoddict.s_class = self
-
-        w_superclass = w_self._fetch(self.space, 
constants.CLASS_SUPERCLASS_INDEX)
-        if w_superclass.is_same_object(self.space.w_nil):
-            self._s_superclass = None
-        else:
-            assert isinstance(w_superclass, model.W_PointersObject)
-            self.store_w_superclass(w_superclass)
-        self.changed()
-
-    @jit.unroll_safe
-    def flush_caches(self):
-        look_in_shadow = self
-        while look_in_shadow is not None:
-            s_method = look_in_shadow.s_methoddict().sync_cache()
-            look_in_shadow = look_in_shadow._s_superclass
-
-    def guess_class_name(self):
-        if self.name != '':
-            return self.name
-        w_self = self.w_self()
-        w_name = None
-
-        # read the name
-        if w_self.size() > constants.CLASS_NAME_INDEX:
-            w_name = w_self._fetch(self.space, constants.CLASS_NAME_INDEX)
-        else:
+        elif n0 == constants.CLASS_NAME_INDEX:
+            self.store_w_name(w_val)
+        elif n0 == (self.size() - 1):
             # Some heuristic to find the classname
             # Only used for debugging
             # XXX This is highly experimental XXX
@@ -184,19 +184,48 @@
             # we are probably holding a metaclass instead of a class.
             # metaclasses hold a pointer to the real class in the last
             # slot. This is pos 6 in mini.image and higher in squeak3.9
-            w_realclass = w_self._fetch(self.space, w_self.size() - 1)
-            if (isinstance(w_realclass, model.W_PointersObject)
-                and w_realclass.size() > constants.CLASS_NAME_INDEX):
+            if (isinstance(w_val, model.W_PointersObject)
+                and w_val.size() > constants.CLASS_NAME_INDEX):
                 # TODO ADD TEST WHICH GOES OVER THIS PART
-                w_name = w_realclass._fetch(self.space, 
constants.CLASS_NAME_INDEX)
+                
self.store_w_name(w_realclass.fetch(constants.CLASS_NAME_INDEX))
             else:
                 return
+        else:
+            return
+        # Some of the special info has changed -> Switch version.
+        self.changed()
+    
+    def store_w_superclass(self, w_class):
+        if w_class is None or w_class.is_same_object(model.w_nil):
+            self._s_superclass = None
+        else:
+            assert isinstance(w_class, model.W_PointersObject)
+            s_scls = w_class.as_class_get_shadow(self.space)
+            if self._s_superclass is s_scls:
+                return
+            if self._s_superclass is not None:
+                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[s_other] = None
+
+    def detach_s_class(self, s_other):
+        del self.subclass_s[s_other]
+    
+    def store_w_name(self, w_name):
         if isinstance(w_name, model.W_BytesObject):
             self.name = w_name.as_string()
         else:
             self.name = None
-        self.changed()
+    
+    @jit.unroll_safe
+    def flush_method_caches(self):
+        look_in_shadow = self
+        while look_in_shadow is not None:
+            look_in_shadow.s_methoddict().sync_method_cache()
+            look_in_shadow = look_in_shadow._s_superclass
 
     def new(self, extrasize=0):
         w_cls = self.w_self()
@@ -224,16 +253,19 @@
         return w_new
 
     def w_methoddict(self):
-        return self.w_self()._fetch(self.space, 
constants.CLASS_METHODDICT_INDEX)
+        return self._s_methoddict.w_self()
 
     def s_methoddict(self):
+        if not hasattr(self, "_s_methoddict"):
+            import pdb; pdb.set_trace()
         return self._s_methoddict
 
     def s_superclass(self):
-        if self._s_superclass is None:
-            return None
         return self._s_superclass
 
+    def getname(self):
+        return "%s class" % (self.name or '?',)
+
     # _______________________________________________________________
     # Methods for querying the format word, taken from the blue book:
     #
@@ -264,24 +296,23 @@
         " Number of named instance variables for each instance of this class "
         return self._instance_size
 
-    def store_w_superclass(self, w_class):
-        if w_class is None:
-            self._s_superclass = None
-        else:
-            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)
+    # _______________________________________________________________
+    # Other Methods
 
-    def attach_s_class(self, s_other):
-        self.subclass_s[s_other] = None
+    def __repr__(self):
+        return "<ClassShadow %s>" % (self.name or '?',)
 
-    def detach_s_class(self, s_other):
-        del self.subclass_s[s_other]
+    @constant_for_version
+    def lookup(self, w_selector):
+        import pdb; pdb.set_trace()
+        
+        look_in_shadow = self
+        while look_in_shadow is not None:
+            s_method = look_in_shadow.s_methoddict().find_selector(w_selector)
+            if s_method is not None:
+                return s_method
+            look_in_shadow = look_in_shadow._s_superclass
+        raise MethodNotFound(self, w_selector)
 
     def changed(self):
         self.superclass_changed(version.Version())
@@ -292,28 +323,12 @@
             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:
-
-    def __repr__(self):
-        return "<ClassShadow %s>" % (self.name or '?',)
-
-    @constant_for_version
-    def lookup(self, w_selector):
-        look_in_shadow = self
-        while look_in_shadow is not None:
-            s_method = look_in_shadow.s_methoddict().find_selector(w_selector)
-            if s_method is not None:
-                return s_method
-            look_in_shadow = look_in_shadow._s_superclass
-        raise MethodNotFound(self, w_selector)
-
-
+        
     # _______________________________________________________________
     # Methods used only in testing
 
     def inherits_from(self, s_superclass):
+        "NOT_RPYTHON"     # this is only for testing.
         classshadow = self
         while classshadow is not None:
             if classshadow is s_superclass:
@@ -328,7 +343,7 @@
             w_methoddict = model.W_PointersObject(self.space, None, 2)
             w_methoddict._store(self.space, 1, 
model.W_PointersObject(self.space, None, 0))
             self._s_methoddict = 
w_methoddict.as_methoddict_get_shadow(self.space)
-            self.s_methoddict().sync_cache()
+            self.s_methoddict().sync_method_cache()
         self.s_methoddict().invalid = False
 
     def installmethod(self, w_selector, w_method):
@@ -340,7 +355,7 @@
         if isinstance(w_method, model.W_CompiledMethod):
             s_method.w_compiledin = self.w_self()
 
-class MethodDictionaryShadow(AbstractShadow):
+class MethodDictionaryShadow(ListStorageShadow):
 
     _immutable_fields_ = ['invalid?', 's_class']
     _attrs_ = ['methoddict', 'invalid', 's_class']
@@ -349,23 +364,21 @@
         self.invalid = True
         self.s_class = None
         self.methoddict = {}
-        AbstractShadow.__init__(self, space, w_self)
+        ListStorageShadow.__init__(self, space, w_self, 0)
 
     def find_selector(self, w_selector):
         if self.invalid:
             return None # we may be invalid if Smalltalk code did not call 
flushCache
         return self.methoddict.get(w_selector, None)
 
-    def update(self): return self.sync_cache()
-
     # Remove update call for changes to ourselves:
     # Whenever a method is added, it's keyword is added to w_self, then the
     # w_compiled_method is added to our observee.
-        # Sync_cache at this point would not have the desired effect, because 
in
-        # the Smalltalk Implementation, the dictionary changes first. 
Afterwards
-        # its contents array is filled with the value belonging to the new key.
+    # sync_method_cache at this point would not have the desired effect, 
because in
+    # the Smalltalk Implementation, the dictionary changes first. Afterwards
+    # its contents array is filled with the value belonging to the new key.
     def store(self, n0, w_value):
-        AbstractShadow.store(self, n0, w_value)
+        ListStorageShadow.store(self, n0, w_value)
         self.invalid = True
 
     def _as_md_entry(self, w_selector):
@@ -374,17 +387,17 @@
         else:
             return "%r" % w_selector # use the pointer for this
 
-    def sync_cache(self):
-        if self.w_self().size() == 0:
+    def sync_method_cache(self):
+        if self.size() == 0:
             return
-        w_values = self.w_self()._fetch(self.space, 
constants.METHODDICT_VALUES_INDEX)
+        w_values = self.fetch(self.space, constants.METHODDICT_VALUES_INDEX)
         assert isinstance(w_values, model.W_PointersObject)
         s_values = w_values.as_observed_get_shadow(self.space)
         s_values.notify(self)
-        size = self.w_self().size() - constants.METHODDICT_NAMES_INDEX
+        size = self.size() - constants.METHODDICT_NAMES_INDEX
         self.methoddict = {}
         for i in range(size):
-            w_selector = self.w_self()._fetch(self.space, 
constants.METHODDICT_NAMES_INDEX+i)
+            w_selector = self.w_self().fetch(self.space, 
constants.METHODDICT_NAMES_INDEX+i)
             if not w_selector.is_same_object(self.space.w_nil):
                 if not isinstance(w_selector, model.W_BytesObject):
                     pass
@@ -392,7 +405,7 @@
                     #       Putting any key in the methodDict and running with
                     #       perform is actually supported in Squeak
                     # raise ClassShadowError("bogus selector in method dict")
-                w_compiledmethod = w_values._fetch(self.space, i)
+                w_compiledmethod = w_values.fetch(self.space, i)
                 if not isinstance(w_compiledmethod, model.W_CompiledMethod):
                     raise ClassShadowError("The methoddict must contain "
                                        "CompiledMethods only, for now. "
@@ -434,17 +447,6 @@
                 assert e.s_context == self
         w_self.initialize_storage(self.space, 0)
 
-    # def detach_shadow(self):
-    #     w_self = self.w_self()
-    #     assert isinstance(w_self, model.W_PointersObject)
-    #     w_self._vars = [self.space.w_nil] * self._w_self_size
-    #     for i in range(self._w_self_size):
-    #         self.copy_to_w_self(i)
-
-    def copy_from_w_self(self, n0):
-        self.store(n0, self.w_self()._fetch(self.space, n0))
-    def copy_to_w_self(self, n0):
-        self.w_self()._store(self.space, n0, self.fetch(n0))
 
 class ContextPartShadow(AbstractRedirectingShadow):
 
@@ -1100,29 +1102,25 @@
 
     @elidable_for_version
     def fetch(self, n0):
-        return self._w_self._fetch(self.space, n0)
+        return AbstractCachingShadow.fetch(self, n0)
 
     def store(self, n0, w_value):
         res = self._w_self._store(self.space, n0, w_value)
         self.changed()
         return res
 
-    def update(self): pass
 
-
-class ObserveeShadow(AbstractShadow):
+class ObserveeShadow(ListStorageShadow):
     _attrs_ = ['dependent']
     def __init__(self, space, w_self):
-        AbstractShadow.__init__(self, space, w_self)
+        ListStorageShadow.__init__(self, space, w_self, 0)
         self.dependent = None
 
     def store(self, n0, w_value):
-        AbstractShadow.store(self, n0, w_value)
+        ListStorageShadow.store(self, n0, w_value)
         self.dependent.update()
 
     def notify(self, dependent):
         if self.dependent is not None and dependent is not self.dependent:
             raise RuntimeError('Meant to be observed by only one value, so 
far')
         self.dependent = dependent
-
-    def update(self): pass
diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py
--- a/spyvm/squeakimage.py
+++ b/spyvm/squeakimage.py
@@ -230,7 +230,6 @@
         self.init_g_objects()
         self.init_w_objects()
         self.fillin_w_objects()
-        self.synchronize_shadows()
 
     def read_version(self):
         # 1 word version
@@ -288,8 +287,11 @@
                 if self.special_object(0).w_object is not self.space.w_nil:
                    raise Warning('Object found in multiple places in the 
special objects array')
         # assign w_objects for objects that are already in classtable
+        import pdb; pdb.set_trace()
         for name, so_index in 
constants.classes_in_special_object_table.items():
             w_object = self.space.classtable["w_" + name]
+            if not w_object:
+                import pdb; pdb.set_trace()
             if self.special_object(so_index).w_object is None:
                 self.special_object(so_index).w_object = w_object
             else:
@@ -302,13 +304,7 @@
 
     def fillin_w_objects(self):
         for chunk in self.chunks.itervalues():
-            chunk.g_object.w_object.fillin(self.space, chunk.g_object)
-
-    def synchronize_shadows(self):
-        for chunk in self.chunks.itervalues():
-            casted = chunk.g_object.w_object
-            if isinstance(casted, model.W_PointersObject) and 
casted.has_shadow():
-                casted.shadow.update()
+            chunk.g_object.fillin(self.space)
 
     def init_compactclassesarray(self):
         """ from the blue book (CompiledMethod Symbol Array PseudoContext 
LargePositiveInteger nil MethodDictionary Association Point Rectangle nil 
TranslatedMethod BlockContext MethodContext nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil ) """
@@ -428,6 +424,7 @@
     def __init__(self, space):
         self.space = space
         self.reader = None
+        self.filled_in = False
 
     def isinitialized(self):
         return self.reader is not None
@@ -568,9 +565,20 @@
             raise CorruptImageError("Expected %d words, got %d" % 
(required_len, len(words)))
         return words
 
+    def fillin(self, space):
+        if self == self.reader.special_object(6):
+            import pdb; pdb.set_trace()
+        
+        if not self.filled_in:
+            self.filled_in = True
+            self.w_object.fillin(space, self)
+        
+    def get_g_pointers(self):
+        assert self.pointers is not None
+        return self.pointers
+    
     def get_pointers(self):
-        assert self.pointers is not None
-        return [g_object.w_object for g_object in self.pointers]
+        return [g_object.w_object for g_object in self.get_g_pointers()]
 
     def get_class(self):
         w_class = self.g_class.w_object
diff --git a/spyvm/strategies.py b/spyvm/strategies.py
--- a/spyvm/strategies.py
+++ b/spyvm/strategies.py
@@ -7,7 +7,7 @@
 from rpython.rlib.objectmodel import import_from_mixin
 from rpython.rlib.rfloat import string_to_float
 
-class AbstractStorageStrategy(object):
+class AbstractStorageStrategy(shadow.AbstractShadow):
     _immutable_fields_ = []
     _attrs_ = []
     _settled_ = True
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to