[pypy-commit] lang-smalltalk strategies3: Fixing things up

anton_gulenko noreply at buildbot.pypy.org
Mon Jul 28 10:11:12 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: strategies3
Changeset: r988:a77d13fd8840
Date: 2014-03-19 12:42 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/a77d13fd8840/

Log:	Fixing things up

diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py
--- a/spyvm/fieldtypes.py
+++ b/spyvm/fieldtypes.py
@@ -9,20 +9,26 @@
     _attrs_ = []
     _settled_ = True
 
-    def __init__(self):
-        pass
-    def fetch(self, w_obj, n0):
+    def fetch(self, space, w_obj, n0):
         raise NotImplementedError("Abstract base class")
-    def store(self, w_obj, n0, w_val):
+    def store(self, space, w_obj, n0, w_val):
         raise NotImplementedError("Abstract base class")
     def size_of(self, w_obj):
         raise NotImplementedError("Abstract base class")
-    def initial_storage(self, size, default_element):
+    
+    def initial_storage(self, space, size):
         raise NotImplementedError("Abstract base class")
-    def storage_for_list(self, collection):
+    def storage_for_list(self, space, collection):
         raise NotImplementedError("Abstract base class")
-    def all_vars(self, w_obj):
-        return [self.fetch(w_obj, i) for i in range(0, self.size_of(w_obj))]
+    def copy_storage_from(self, space, w_obj, reuse_storage=False):
+        old_strategy = w_obj.strategy
+        if old_strategy == self and reuse_storage:
+            return w_obj.get_storage()
+        if isinstance(old_strategy, AllNilStorageStrategy):
+            return self.initial_storage(space, old_strategy.size_of(w_obj))
+        else:
+            # This can be overridden and optimized (reuse_storage flag, less temporary storage)
+            return self.storage_for_list(space, w_obj.fetch_all(space))
 
 class SingletonMeta(type):
     def __new__(cls, name, bases, dct):
@@ -43,14 +49,14 @@
     erase, unerase = rerased.new_static_erasing_pair("list-storage-strategy")
     import_from_mixin(BasicStorageStrategyMixin)
     
-    def fetch(self, w_obj, n0):
+    def fetch(self, space, w_obj, n0):
         return self.storage(w_obj)[n0]
-    def store(self, w_obj, n0, w_val):
+    def store(self, space, w_obj, n0, w_val):
         self.storage(w_obj)[n0] = w_val
     def size_of(self, w_obj):
         return len(self.storage(w_obj))
-    def initial_storage(self, size, default_element):
-        return self.erase([default_element] * size)
+    def initial_storage(self, space, size):
+        return self.erase([model.w_nil] * size)
     def storage_for_list(self, space, collection):
         return self.erase([x for x in collection])
 
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -507,12 +507,12 @@
     def fetch(self, space, n0):
         if self.has_shadow():
             return self._shadow.fetch(n0)
-        return self._fetch(n0)
+        return self._fetch(space, n0)
 
     def store(self, space, n0, w_value):
         if self.has_shadow():
             return self._shadow.store(n0, w_value)
-        return self._store(n0, w_value)
+        return self._store(space, n0, w_value)
 
     def varsize(self, space):
         return self.size() - self.instsize(space)
@@ -626,39 +626,36 @@
         """Create new object with size = fixed + variable size."""
         W_AbstractPointersObject.__init__(self, space, w_class, size)
         self.strategy = strategy_of_size(self.s_class, size)
-        self.storage = self.strategy.initial_storage(size, w_nil)
+        self.storage = self.strategy.initial_storage(space, size)
 
     def fillin(self, space, g_self):
         W_AbstractPointersObject.fillin(self, space, g_self)
         from spyvm.fieldtypes import strategy_for_list
         pointers = g_self.get_pointers()
         self.strategy = strategy_for_list(self.s_class, pointers)
-        self.storage = self.strategy.storage_for_list(pointers)
+        self.storage = self.strategy.storage_for_list(space, pointers)
 
     def get_strategy(self):
+        # return jit.promote(self.strategy)
         return self.strategy
         
     def get_storage(self):
         return self.storage
         
-    def all_vars(self):
-        return self.strategy.all_vars(self)
+    def all_vars(self, space):
+        return [self.strategy.fetch(space, self, i) for i in range(self.basic_size())]
     
     def set_all_vars(self, collection):
-        # TODO reuse storage if possible
-        self.storage = self.strategy.storage_for_list(collection)
+        self.storage = self.strategy.storage_for_list(space, collection)
     
-    def _fetch(self, n0):
-        strategy = jit.promote(self.strategy)
-        return strategy.fetch(self, n0)
+    def _fetch(self, space, n0):
+        return self.get_strategy().fetch(space, self, n0)
 
-    def _store(self, n0, w_value):
-        strategy = jit.promote(self.strategy)
-        return strategy.store(self, n0, w_value)
+    def _store(self, space, n0, w_value):
+        return self.get_strategy().store(space, self, n0, w_value)
 
     def basic_size(self):
-        strategy = jit.promote(self.strategy)
-        return strategy.size_of(self)
+        return self.get_strategy().size_of(self)
 
     def become(self, w_other):
         if not isinstance(w_other, W_PointersObject):
@@ -672,7 +669,7 @@
         length = self.strategy.size_of(self)
         w_result = W_PointersObject(self.space, self.getclass(space), length)
         cloned_vars = [self.fetch(space, i) for i in range(length)]
-        w_result.storage = w_result.strategy.storage_for_list(cloned_vars)
+        w_result.storage = w_result.strategy.storage_for_list(space, cloned_vars)
         return w_result
 
     def fieldtype(self):
@@ -690,11 +687,11 @@
     def fillin(self, space, g_self):
         raise NotImplementedError("we don't expect weak objects in a fresh image")
 
-    def _fetch(self, n0):
+    def _fetch(self, space, n0):
         weakobj = self._weakvars[n0]
         return weakobj() or w_nil
 
-    def _store(self, n0, w_value):
+    def _store(self, space, n0, w_value):
         assert w_value is not None
         self._weakvars[n0] = weakref.ref(w_value)
 
@@ -1193,7 +1190,10 @@
             if isinstance(w_candidate, W_PointersObject):
                 c_shadow = w_candidate._shadow
                 if c_shadow is None and w_candidate.size() >= 2:
-                    w_class = w_candidate._fetch(1)
+                    space = None
+                    if self._shadow:
+                        space = self._shadow.space
+                    w_class = w_candidate._fetch(space, 1)
                     if isinstance(w_class, W_PointersObject):
                         d_shadow = w_class._shadow
                         if isinstance(d_shadow, shadow.ClassShadow):
@@ -1260,7 +1260,7 @@
     def as_compiledmethod_get_shadow(self, space=None):
         from shadow import CompiledMethodShadow
         if self._shadow is None:
-            self._shadow = CompiledMethodShadow(self)
+            self._shadow = CompiledMethodShadow(space, self)
         return self._shadow
 
     def literalat0(self, space, index0):
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -165,7 +165,7 @@
             from spyvm.fieldtypes import ListStorageStrategy
             w_nil.space = self
             w_nil.strategy = ListStorageStrategy.singleton
-            w_nil.storage = w_nil.strategy.initial_storage(0, None)
+            w_nil.storage = w_nil.strategy.initial_storage(self, 0)
             w_nil.s_class = self.classtable['w_UndefinedObject'].as_class_get_penumbra(self)
             return w_nil
         w_nil = self.w_nil = patch_nil(model.w_nil)
diff --git a/spyvm/plugins/bitblt.py b/spyvm/plugins/bitblt.py
--- a/spyvm/plugins/bitblt.py
+++ b/spyvm/plugins/bitblt.py
@@ -756,8 +756,8 @@
         w_offset = self.fetch(4)
         assert isinstance(w_offset, model.W_PointersObject)
         if not w_offset is self.space.w_nil:
-            self.offsetX = self.intOrIfNil(w_offset._fetch(0), 0)
-            self.offsetY = self.intOrIfNil(w_offset._fetch(1), 0)
+            self.offsetX = self.intOrIfNil(w_offset._fetch(self.space, 0), 0)
+            self.offsetY = self.intOrIfNil(w_offset._fetch(self.space, 1), 0)
         self.pixPerWord = 32 / self.depth
         self.pitch = (self.width + (self.pixPerWord - 1)) / self.pixPerWord | 0
         if self.w_bits.size() < (self.pitch * self.height):
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -374,7 +374,7 @@
         print ("%s" % w_message).replace('\r', '\n')
         print ("%s" % s_frame.peek(1)).replace('\r', '\n')
         if isinstance(w_message, model.W_PointersObject):
-            print ('%s' % w_message.all_vars()).replace('\r', '\n')
+            print ('%s' % w_message.all_vars(interp.space)).replace('\r', '\n')
         # raise Exit('Probably Debugger called...')
     raise PrimitiveFailedError()
 
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -23,9 +23,9 @@
         self.space = space
         self._w_self = w_self
     def fetch(self, n0):
-        return self.w_self()._fetch(n0)
+        return self.w_self()._fetch(self.space, n0)
     def store(self, n0, w_value):
-        return self.w_self()._store(n0, w_value)
+        return self.w_self()._store(self.space, n0, w_value)
     def size(self):
         return self.w_self().basic_size()
     def w_self(self):
@@ -109,7 +109,7 @@
         # read and painfully decode the format
         try:
             classformat = self.space.unwrap_int(
-                w_self._fetch(constants.CLASS_FORMAT_INDEX))
+                w_self._fetch(self.space, constants.CLASS_FORMAT_INDEX))
             # 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>
@@ -149,19 +149,19 @@
             else:
                 raise ClassShadowError("unknown format %d" % (format,))
         except UnwrappingError:
-            assert w_self._fetch(constants.CLASS_FORMAT_INDEX) is self.space.w_nil
+            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(constants.CLASS_METHODDICT_INDEX)
+        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(constants.CLASS_SUPERCLASS_INDEX)
+        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:
@@ -184,7 +184,7 @@
 
         # read the name
         if w_self.size() > constants.CLASS_NAME_INDEX:
-            w_name = w_self._fetch(constants.CLASS_NAME_INDEX)
+            w_name = w_self._fetch(self.space, constants.CLASS_NAME_INDEX)
         else:
             # Some heuristic to find the classname
             # Only used for debugging
@@ -193,11 +193,11 @@
             # 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(w_self.size() - 1)
+            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):
                 # TODO ADD TEST WHICH GOES OVER THIS PART
-                w_name = w_realclass._fetch(constants.CLASS_NAME_INDEX)
+                w_name = w_realclass._fetch(self.space, constants.CLASS_NAME_INDEX)
             else:
                 return
 
@@ -233,7 +233,7 @@
         return w_new
 
     def w_methoddict(self):
-        return self.w_self()._fetch(constants.CLASS_METHODDICT_INDEX)
+        return self.w_self()._fetch(self.space, constants.CLASS_METHODDICT_INDEX)
 
     def s_methoddict(self):
         return self._s_methoddict
@@ -335,7 +335,7 @@
         "NOT_RPYTHON"     # this is only for testing.
         if self._s_methoddict is None:
             w_methoddict = model.W_PointersObject(self.space, None, 2)
-            w_methoddict._store(1, model.W_PointersObject(self.space, None, 0))
+            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().invalid = False
@@ -386,14 +386,14 @@
     def sync_cache(self):
         if self.w_self().size() == 0:
             return
-        w_values = self.w_self()._fetch(constants.METHODDICT_VALUES_INDEX)
+        w_values = self.w_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
         self.methoddict = {}
         for i in range(size):
-            w_selector = self.w_self()._fetch(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
@@ -401,7 +401,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(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. "
@@ -441,7 +441,7 @@
                 self.copy_from_w_self(i)
             except error.SenderChainManipulation, e:
                 assert e.s_context == self
-        w_self.storage = w_self.strategy.initial_storage(0, None)
+        w_self.storage = w_self.strategy.initial_storage(self.space, 0)
 
     # def detach_shadow(self):
     #     w_self = self.w_self()
@@ -451,9 +451,9 @@
     #         self.copy_to_w_self(i)
 
     def copy_from_w_self(self, n0):
-        self.store(n0, self.w_self()._fetch(n0))
+        self.store(n0, self.w_self()._fetch(self.space, n0))
     def copy_to_w_self(self, n0):
-        self.w_self()._store(n0, self.fetch(n0))
+        self.w_self()._store(self.space, n0, self.fetch(n0))
 
 class ContextPartShadow(AbstractRedirectingShadow):
 
@@ -1031,11 +1031,12 @@
               "literals", "bytecodeoffset",
               "literalsize", "_tempsize", "_primitive",
               "argsize", "islarge",
-              "w_compiledin", "version"]
+              "w_compiledin", "version", "space"]
     _immutable_fields_ = ["version?", "_w_self"]
 
-    def __init__(self, w_compiledmethod):
+    def __init__(self, space, w_compiledmethod):
         self._w_self = w_compiledmethod
+        self.space = space
         self.update()
 
     def w_self(self):
@@ -1110,11 +1111,11 @@
     @jit.elidable
     def safe_fetch(self, n0, version):
         assert version is self.version
-        return self._w_self._fetch(n0)
+        return self._w_self._fetch(self.space, n0)
 
     def store(self, n0, w_value):
         self.version = Version()
-        return self._w_self._store(n0, w_value)
+        return self._w_self._store(self.space, n0, w_value)
 
     def update(self): pass
 
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -218,7 +218,7 @@
         step_in_interp(s_frame)
         assert s_frame.stack() == []
         for test_index in range(8):
-            print w_frame.all_vars()
+            print w_frame.all_vars(space)
             if test_index == index:
                 assert s_frame.gettemp(test_index) == space.w_true
             else:
diff --git a/spyvm/test/test_primitives.py b/spyvm/test/test_primitives.py
--- a/spyvm/test/test_primitives.py
+++ b/spyvm/test/test_primitives.py
@@ -14,7 +14,7 @@
 
 class MockFrame(model.W_PointersObject):
     def __init__(self, stack):
-        self.set_all_vars([None] * 6 + stack + [space.w_nil] * 6)
+        self.set_all_vars(space, [None] * 6 + stack + [space.w_nil] * 6)
         s_self = self.as_blockcontext_get_shadow()
         s_self.init_stack_and_temps()
         s_self.reset_stack()
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
@@ -240,15 +240,15 @@
     s_methoddict = s_class.s_methoddict()
     s_methoddict.sync_cache()
     i = 0
-    key = s_methoddict.w_self()._fetch(constants.METHODDICT_NAMES_INDEX+i)
+    key = s_methoddict.w_self()._fetch(space, constants.METHODDICT_NAMES_INDEX+i)
     while key is space.w_nil:
         i = i + 1
-        key = s_methoddict.w_self()._fetch(constants.METHODDICT_NAMES_INDEX+i)
+        key = s_methoddict.w_self()._fetch(space, constants.METHODDICT_NAMES_INDEX+i)
 
     assert (s_class.lookup(key) is foo.as_compiledmethod_get_shadow(space)
             or s_class.lookup(key) is bar.as_compiledmethod_get_shadow(space))
     # change that entry
-    w_array = s_class.w_methoddict()._fetch(constants.METHODDICT_VALUES_INDEX)
+    w_array = s_class.w_methoddict()._fetch(space, constants.METHODDICT_VALUES_INDEX)
     version = s_class.version
     w_array.atput0(space, i, baz)
 
@@ -268,7 +268,7 @@
 
     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)
+    w_ary = s_md._w_self._fetch(space, constants.METHODDICT_VALUES_INDEX)
     s_md._w_self.atput0(space, 0, key)
     w_ary.atput0(space, 0, w_method)
 


More information about the pypy-commit mailing list