Author: Anton Gulenko <[email protected]>
Branch: strategies-tagging
Changeset: r669:f63aa764c7bf
Date: 2014-03-20 11:39 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/f63aa764c7bf/

Log:    Refactoring to remove rerased and use two separate variables for
        wrapped and unwrapped storage.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -653,16 +653,15 @@
 strategy_stats = StrategyStatistics()
 
 class W_PointersObject(W_AbstractPointersObject):
-    _attrs_ = ['_storage', 'strategy']
+    _attrs_ = ['_size', '_storage', 'int_storage', 'strategy']
 
     @jit.unroll_safe
     def __init__(self, space, w_class, size):
         from spyvm.strategies import strategy_of_size
         """Create new object with size = fixed + variable size."""
         W_AbstractPointersObject.__init__(self, space, w_class, size)
-        # TODO - setting strategy/storage is useless if fillin() will be 
called afterwards.
         self.strategy = strategy_of_size(self.s_class, size)
-        self.set_storage(self.strategy.initial_storage(space, size))
+        self.set_storage(space, size)
         self.log_strategy_operation("Initialized")
     
     def log_strategy_operation(self, op, old_strategy=None):
@@ -680,11 +679,12 @@
             if strategy_stats.do_log:
                 strategy_stats.log_operation(op, new_strategy_tag, 
old_strategy_tag, classname, size)
     
-    def set_storage(self, storage):
-        self._storage = storage
-    
-    def get_storage(self):
-        return self._storage
+    def set_storage(self, space, size):
+        self._size = size
+        if self.strategy.uses_int_storage:
+            self.int_storage = self.strategy.initial_int_storage(space, size)
+        else:
+            self._storage = self.strategy.initial_storage(space, size)
     
     def get_strategy(self):
         return self.strategy
@@ -692,7 +692,11 @@
     def fillin_pointers(self, space, collection):
         from spyvm.strategies import strategy_for_list
         self.strategy = strategy_for_list(self.s_class, collection)
-        self.set_storage(self.strategy.storage_for_list(space, collection))
+        self._size = len(collection)
+        if self.strategy.uses_int_storage:
+            self.int_storage = self.strategy.int_storage_for_list(space, 
collection)
+        else:
+            self._storage = self.strategy.storage_for_list(space, collection)
     
     def fillin(self, space, g_self):
         W_AbstractPointersObject.fillin(self, space, g_self)
@@ -701,10 +705,12 @@
 
     def switch_strategy(self, space, new_strategy):
         assert self.strategy != new_strategy
-        new_storage = new_strategy.copy_storage_from(space, self, 
reuse_storage=True)
+        if new_strategy.uses_int_storage:
+            self.int_storage = new_strategy.copy_int_storage_from(space, self, 
reuse_storage=True)
+        else:
+            self._storage = new_strategy.copy_storage_from(space, self, 
reuse_storage=True)
         old_strategy = self.strategy
         self.strategy = new_strategy
-        self.set_storage(new_storage)
         self.log_strategy_operation("Switched", old_strategy)
 
     def store_with_new_strategy(self, space, new_strategy, n0, w_val):
@@ -735,15 +741,15 @@
         return self.get_strategy().store(space, self, n0, w_value)
 
     def basic_size(self):
-        return self.get_strategy().size_of(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_storage = self._storage
-        self.set_storage(w_other._storage)
-        w_other.set_storage(self_storage)
+        self._size, w_other._size = w_other._size, self._size
+        self._storage, w_other._storage = w_other._storage, self._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
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -165,7 +165,7 @@
             from spyvm.strategies import ListStorageStrategy
             w_nil.space = self
             w_nil.strategy = ListStorageStrategy.singleton
-            w_nil.set_storage(w_nil.strategy.initial_storage(self, 0))
+            w_nil.set_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/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -432,7 +432,7 @@
                 self.copy_from_w_self(i)
             except error.SenderChainManipulation, e:
                 assert e.s_context == self
-        w_self.set_storage(w_self.strategy.initial_storage(self.space, 0))
+        w_self.set_storage(self.space, 0)
 
     # def detach_shadow(self):
     #     w_self = self.w_self()
diff --git a/spyvm/strategies.py b/spyvm/strategies.py
--- a/spyvm/strategies.py
+++ b/spyvm/strategies.py
@@ -14,6 +14,7 @@
     _attrs_ = []
     _settled_ = True
     strategy_tag = 'abstract'
+    uses_int_storage = False
     
     def __init__(self):
         pass
@@ -31,14 +32,23 @@
     
     def initial_storage(self, space, size):
         raise NotImplementedError("Abstract base class")
+    def initial_int_storage(self, space, size):
+        raise NotImplementedError("Abstract base class")
     def storage_for_list(self, space, collection):
         raise NotImplementedError("Abstract base class")
+    def int_storage_for_list(self, space, collection):
+        raise NotImplementedError("Abstract base class")
+    def copy_int_storage_from(self, space, w_obj, reuse_storage=False):
+        old_strategy = w_obj.strategy
+        if old_strategy == self and reuse_storage:
+            return w_obj.int_storage
+        else:
+            # This can be overridden and optimized (reuse_storage flag, less 
temporary storage)
+            return self.int_storage_for_list(space, w_obj.fetch_all(space))
     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))
+            return w_obj._storage
         else:
             # This can be overridden and optimized (reuse_storage flag, less 
temporary storage)
             return self.storage_for_list(space, w_obj.fetch_all(space))
@@ -51,22 +61,24 @@
 
 class BasicStorageStrategyMixin(object):
     # Concrete class must implement: unerase
+    def size_of(self, w_obj):
+        if self.uses_int_storage:
+            return len(self.int_storage(w_obj))
+        else:
+            return len(self.storage(w_obj))
+    def int_storage(self, w_obj):
+        return w_obj.int_storage
     def storage(self, w_obj):
-        return self.unerase(w_obj.get_storage())
-
-# This is a container for an int-value to be used with a rerased-pair
-class SizeStorage(object):
-    _attrs_ = ['size']
-    _settled_ = True
-    def __init__(self, size):
-        self.size = size
+        return w_obj._storage
+    def erase(self, a): return a
+    def unerase(self, a): return a
 
 # this is the typical "initial" storage strategy, for when every slot
 # in a var-sized object is still nil. No storage is allocated except for
 # holding the size of the object.
 class AllNilStorageStrategy(AbstractStorageStrategy):
     __metaclass__ = SingletonMeta
-    erase, unerase = rerased.new_static_erasing_pair("all-nil-strategy")
+    # erase, unerase = rerased.new_static_erasing_pair("all-nil-strategy")
     import_from_mixin(BasicStorageStrategyMixin)
     strategy_tag = 'allnil'
     
@@ -82,21 +94,19 @@
                 return w_obj.store_with_new_strategy(space, 
TaggingSmallIntegerStorageStrategy.singleton, n0, w_val)
         return w_obj.store_with_new_strategy(space, 
ListStorageStrategy.singleton, n0, w_val)
         
-    def size_of(self, w_obj):
-        return self.storage(w_obj).size
     def initial_storage(self, space, size):
-        return self.erase(SizeStorage(size))
+        return []
     def storage_for_list(self, space, collection):
-        return self.erase(SizeStorage(len(collection)))
+        return []
     def copy_storage_from(self, space, w_obj, reuse_storage=False):
-        return self.erase(SizeStorage(w_obj.basic_size()))
+        return []
 
 # 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):
     __metaclass__ = SingletonMeta
-    erase, unerase = rerased.new_static_erasing_pair("list-storage-strategy")
+    # erase, unerase = rerased.new_static_erasing_pair("list-storage-strategy")
     import_from_mixin(BasicStorageStrategyMixin)
     strategy_tag = 'list'
     
@@ -105,8 +115,6 @@
     def store(self, space, w_obj, n0, w_val):
         # TODO enable generalization by maintaining a counter of elements that 
are nil.
         self.storage(w_obj)[n0] = w_val
-    def size_of(self, w_obj):
-        return len(self.storage(w_obj))
     def erased_list(self, list):
         make_sure_not_resized(list)
         return self.erase(list)
@@ -117,147 +125,13 @@
     def copy_storage_from(self, space, w_obj, reuse_storage=False):
         length = w_obj.basic_size()
         return self.erased_list([w_obj.strategy.fetch(space, w_obj, i) for i 
in range(length)])
-    
-class DenseStorage(object):
-    # Subclass must provide attribute: default_element
-    _immutable_fields_ = ['arr']
-    _attrs_ = ['arr', '_from', '_to']
-    _settled_ = True
-    
-    def __init__(self, _from, _to, size):
-        self._from = _from # first used index ("inclusive")
-        self._to = _to # first unused index ("exclusive")
-        self.arr = [self.default_element] * size
-        make_sure_not_resized(self.arr)
-
-class DenseStorageStrategyMixin(object):
-    # Concrete class must implement: storage, erase, do_fetch, do_store, 
sparse_strategy
-    # Concrete class must provide attributes: storage_type (subclass of 
DenseStorage)
-    
-    def fetch(self, space, w_obj, n0):
-        store = self.storage(w_obj)
-        if n0 < store._from or n0 >= store._to:
-            return model.w_nil
-        return self.do_fetch(space, store.arr, n0)
-    def store(self, space, w_obj, n0, w_val):
-        store = self.storage(w_obj)
-        if not self.can_contain_object(w_val):
-            if w_val == model.w_nil:
-                if store._to - 1 == n0: # Optimize Collection >> remove:
-                    store._to = store._to - 1
-                elif n0 < store._from or store._to <= n0:
-                    pass # Storing nil to an already-nil position
-                elif store._from == n0:
-                    store._from = store._from + 1
-                else:
-                    # Deletion from the middle of the storage. Deoptimize to 
sparse storage.
-                    return w_obj.store_with_new_strategy(space, 
self.sparse_strategy().singleton, n0, w_val)
-                if store._from == store._to:
-                    # Deleted last element. Generelize to AllNilStorage.
-                    w_obj.switch_strategy(space, 
AllNilStorageStrategy.singleton)
-                return
-            else:
-                # Storing a non-int - dehomogenize to ListStorage
-                return w_obj.store_with_new_strategy(space, 
ListStorageStrategy.singleton, n0, w_val)
-        if n0 == store._to: # Optimize Collection >> add:
-            store._to = store._to+1
-        elif store._from <= n0 and n0 < store._to:
-            pass
-        elif n0 == store._from - 1: # It's ok if this wraps around.
-            store._from = store._from-1
-        else:
-            if store._from == store._to:
-                # Initial store to non-zero position.
-                store._from = n0
-                store._to = n0+1
-            else:
-                # Store to a non-dense position. Deoptimize to sparse storage.
-                return w_obj.store_with_new_strategy(space, 
self.sparse_strategy().singleton, n0, w_val)
-        # It is a dense store, so finally store the unwrapped value.
-        self.do_store(space, store.arr, n0, w_val)
-    def initial_storage(self, space, size):
-        return self.erase(self.storage_type(0, 0, size))
-    def storage_for_list(self, space, collection):
-        _from = 0
-        while _from < len(collection) and collection[_from] == model.w_nil:
-            _from = _from+1
-        _to = _from
-        while _to < len(collection) and collection[_to] != model.w_nil:
-            _to = _to+1
-        store = self.storage_type(_from, _to, len(collection))
-        for i in range(_from, _to):
-            self.do_store(space, store.arr, i, collection[i])
-        return self.erase(store)
-
-class SparseStorage(object):
-    _immutable_fields_ = ['arr', 'nil_flags']
-    _attrs_ = ['arr', 'nil_flags']
-    _settled_ = True
-    
-    def __init__(self, arr, nil_flags):
-        self.arr = arr
-        self.nil_flags = nil_flags
-        make_sure_not_resized(self.arr)
-        make_sure_not_resized(self.nil_flags)
-    
-class SparseStorageStrategyMixin(object):
-    # Concrete class must implement: storage, erase, do_fetch, do_store, 
dense_strategy
-    # Concrete class must provide attributes: storage_type (Subclass of 
SparseStorage)
-    
-    def fetch(self, space, w_obj, n0):
-        store = self.storage(w_obj)
-        if store.nil_flags[n0]:
-            return model.w_nil
-        return self.do_fetch(space, store.arr, n0)
-    def store(self, space, w_obj, n0, w_val):
-        store = self.storage(w_obj)
-        if not self.can_contain_object(w_val):
-            if w_val == model.w_nil:
-                # TODO - generelize to AllNilStorage by maintaining a counter 
of nil-elements
-                store.nil_flags[n0] = True
-                return
-            else:
-                # Storing a wrong type - dehomogenize to ListStorage
-                return w_obj.store_with_new_strategy(space, 
ListStorageStrategy.singleton, n0, w_val)
-        store.nil_flags[n0] = False
-        self.do_store(space, store.arr, n0, w_val)
-    def storage_for_size(self, size):
-        # TODO -- for inlining strategy, the size must be extended!!
-        # size = size * self.slots_per_object()
-        return self.storage_type([self.storage_type.default_element] * size, 
[True] * size)
-    def initial_storage(self, space, size):
-        return self.erase(self.storage_for_size(size))
-    def storage_for_list(self, space, collection):
-        length = len(collection)
-        store = self.storage_for_size(length)
-        for i in range(length):
-            if collection[i] != model.w_nil:
-                store.nil_flags[i] = False
-                self.do_store(space, store.arr, i, collection[i])
-        return self.erase(store)
-    def copy_storage_from(self, space, w_obj, reuse_storage=False):
-        old_strategy = w_obj.strategy
-        if isinstance(old_strategy, self.dense_strategy()):
-            # Optimized transition from dense to sparse strategy
-            store = old_strategy.storage(w_obj)
-            return self.erase(self.copy_from_dense_storage(store, 
reuse_storage))
-        else:
-            return AbstractStorageStrategy.copy_storage_from(self, space, 
w_obj, reuse_storage)
-    def copy_from_dense_storage(self, store, reuse_storage):
-        # TODO possible optimization: compare len(arr) with _to-_from, use 
smaller iteration size
-        nil_flags = [True] * len(store.arr)
-        for i in range(store._from, store._to):
-            nil_flags[i] = False
-        arr = store.arr
-        if not reuse_storage:
-            arr = [x for x in arr]
-        return self.storage_type(arr, nil_flags)
 
 class TaggingSmallIntegerStorageStrategy(AbstractStorageStrategy):
     __metaclass__ = SingletonMeta
     strategy_tag = 'tagging-small-int'
-    erase, unerase = 
rerased.new_static_erasing_pair("tagging-small-integer-strategry")
+    # erase, unerase = 
rerased.new_static_erasing_pair("tagging-small-integer-strategry")
     import_from_mixin(BasicStorageStrategyMixin)
+    uses_int_storage = True
     
     @staticmethod
     def wrap(val):
@@ -266,9 +140,6 @@
     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)
@@ -280,35 +151,32 @@
         return True
         
     def fetch(self, space, w_obj, n0):
-        val = self.storage(w_obj)[n0]
-        if (self.is_nil(val)):
+        val = self.int_storage(w_obj)[n0]
+        if val == self.nil_value:
             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)
+        store = self.int_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:
+            if w_val == space.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):
+    def initial_int_storage(self, space, size):
         return self.erase([self.nil_value] * size)
     
-    def storage_for_list(self, space, collection):
+    def int_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:
+            if collection[i] != space.w_nil:
                 store[i] = self.wrap(space.unwrap_int(collection[i]))
         return self.erase(store)
 
@@ -324,8 +192,8 @@
 
 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
+        # This is a weird and rare special case for w_nil
+        return ListStorageStrategy.singleton
     try:
         is_variable = s_containing_class.isvariable()
     except AttributeError:
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
@@ -16,7 +16,7 @@
     def __init__(self, stack):
         size = 6 + len(stack) + 6
         self.strategy = strategies.ListStorageStrategy.singleton
-        self.set_storage(self.strategy.initial_storage(space, size))
+        self.set_storage(space, size)
         self.store_all(space, [None] * 6 + stack + [space.w_nil] * 6)
         s_self = self.as_blockcontext_get_shadow()
         s_self.init_stack_and_temps()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to