[pypy-commit] lang-smalltalk strategies3: Fixing up the system to make some experiments.

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


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

Log:	Fixing up the system to make some experiments.

diff --git a/spyvm/fieldtypes.py b/spyvm/fieldtypes.py
--- a/spyvm/fieldtypes.py
+++ b/spyvm/fieldtypes.py
@@ -2,8 +2,9 @@
 
 from rpython.rlib import rerased
 from rpython.rlib import objectmodel, jit, signature
+from rpython.rlib.objectmodel import import_from_mixin
 
-class AbstractStorageStrategy():
+class AbstractStorageStrategy(object):
     _immutable_fields_ = []
     _attrs_ = []
     _settled_ = True
@@ -23,43 +24,129 @@
     def all_vars(self, w_obj):
         return [self.fetch(w_obj, i) for i in range(0, self.size_of(w_obj))]
 
+class SingletonMeta(type):
+    def __new__(cls, name, bases, dct):
+        result = type.__new__(cls, name, bases, dct)
+        result.singleton = result()
+        return result
+
+class BasicStorageStrategyMixin(object):
+    # Concrete class must implement: unerase
+    def storage(self, w_obj):
+        return self.unerase(w_obj.get_storage())
+
 # This is the regular storage strategy that does not result in any
 # optimizations but can handle every case. Applicable for both
 # fixed-sized and var-sized objects.
 class ListStorageStrategy(AbstractStorageStrategy):
-    erase, unerase = rerased.new_erasing_pair("list-storage-strategy")
-    erase = staticmethod(erase)
-    unerase = staticmethod(unerase)
+    __metaclass__ = SingletonMeta
+    erase, unerase = rerased.new_static_erasing_pair("list-storage-strategy")
+    import_from_mixin(BasicStorageStrategyMixin)
     
     def fetch(self, w_obj, n0):
-        return self.unerase(w_obj.storage)[n0]
+        return self.storage(w_obj)[n0]
     def store(self, w_obj, n0, w_val):
-        self.unerase(w_obj.storage)[n0] = w_val
+        self.storage(w_obj)[n0] = w_val
     def size_of(self, w_obj):
-        return len(self.unerase(w_obj.storage))
+        return len(self.storage(w_obj))
     def initial_storage(self, size, default_element):
         return self.erase([default_element] * size)
-    def storage_for_list(self, collection):
+    def storage_for_list(self, space, collection):
         return self.erase([x for x in collection])
-ListStorageStrategy.singleton = ListStorageStrategy()
 
+class TaggingSmallIntegerStorageStrategy(AbstractStorageStrategy):
+    __metaclass__ = SingletonMeta
+    erase, unerase = rerased.new_static_erasing_pair("tagging-small-integer-strategry")
+    import_from_mixin(BasicStorageStrategyMixin)
+    
+    @staticmethod
+    def wrap(val):
+        return val << 1
+    @staticmethod
+    def unwrap(val):
+        return val >> 1
+    @staticmethod
+    def is_nil(val):
+        return (val & 1) == 1
+    @staticmethod
+    def can_contain(w_val):
+        return isinstance(w_val, model.W_SmallInteger)
+    # TODO - use just a single value to represent nil (max_int-1)
+    # Then, turn wrap/unwrap into noops
+    # also store W_LargePositiveInteger1Word?
+    nil_value = 1
+    
+    def needs_objspace(self):
+        return True
+        
+    def fetch(self, space, w_obj, n0):
+        val = self.storage(w_obj)[n0]
+        if (self.is_nil(val)):
+            return space.w_nil
+        else:
+            return space.wrap_int(self.unwrap(val))
+        
+    def store(self, space, w_obj, n0, w_val):
+        store = self.storage(w_obj)
+        if self.can_contain(w_val):
+            store[n0] = self.wrap(space.unwrap_int(w_val))
+        else:
+            if w_val == model.w_nil:
+                # TODO - generelize to AllNilStorage by maintaining a counter of nil-elements
+                store[n0] = self.nil_value
+            else:
+                # Storing a wrong type - dehomogenize to ListStorage
+                return w_obj.store_with_new_strategy(space, ListStorageStrategy.singleton, n0, w_val)
+        
+    def size_of(self, w_obj):
+        return len(self.storage(w_obj))
+    
+    def initial_storage(self, space, size):
+        return self.erase([self.nil_value] * size)
+    
+    def storage_for_list(self, space, collection):
+        length = len(collection)
+        store = [self.nil_value] * length
+        for i in range(length):
+            if collection[i] != model.w_nil:
+                store[i] = self.wrap(space.unwrap_int(collection[i]))
+        return self.erase(store)
 
-def strategy_of_size(s_class, size):
-    if s_class is None or s_class.isvariable():
+def strategy_of_size(s_containing_class, size):
+    if s_containing_class is None:
+        # This is a weird and rare special case for w_nil
         return ListStorageStrategy.singleton
+    if not s_containing_class.isvariable():
+        return ListStorageStrategy.singleton
+    
+    # A newly allocated object contains only nils.
+    # return AllNilStorageStrategy.singleton
+    return ListStorageStrategy.singleton
+
+def strategy_for_list(s_containing_class, vars):
+    if s_containing_class is None:
+            # This is a weird and rare special case for w_nil
+            return ListStorageStrategy.singleton
+    try:
+        is_variable = s_containing_class.isvariable()
+    except AttributeError:
+        # TODO - This happens during bootstrapping phase, when filling in generic objects.
+        # Ths class object shadows are not yet synchronized.
+        return ListStorageStrategy.singleton
+    
+    if not is_variable:
+        return ListStorageStrategy.singleton
+    
+    is_all_nils = True
+    for w_obj in vars:
+        if w_obj != model.w_nil:
+            is_all_nils = False
+            if not TaggingSmallIntegerStorageStrategy.can_contain(w_obj):
+                # TODO -- here we can still optimize if there is only
+                # one single type in the collection.
+                return ListStorageStrategy.singleton
+    if is_all_nils:
+        return ListStorageStrategy.singleton
+        # return AllNilStorageStrategy.singleton
     else:
-        # TODO -- add AllNilStorageStrategy
-        return ListStorageStrategy.singleton
-
-def strategy_for_list(w_obj, vars):
-    if if s_class is None:
-        return ListStorageStrategy.singleton
-    try:
-        is_variable = w_obj.s_class.isvariable()
-    except AttributeError:
-        return ListStorageStrategy.singleton
-    if is_variable:
-        # TODO - check the contents of vars and choose a good strategy.
-        return ListStorageStrategy.singleton
-    return ListStorageStrategy.singleton
-    
\ No newline at end of file
+        return TaggingSmallIntegerStorageStrategy.singleton
\ No newline at end of file
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -632,9 +632,15 @@
         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, pointers)
+        self.strategy = strategy_for_list(self.s_class, pointers)
         self.storage = self.strategy.storage_for_list(pointers)
 
+    def get_strategy(self):
+        return self.strategy
+        
+    def get_storage(self):
+        return self.storage
+        
     def all_vars(self):
         return self.strategy.all_vars(self)
     


More information about the pypy-commit mailing list