Author: Anton Gulenko <[email protected]>
Branch: rstrategies
Changeset: r1049:dbbcbc97abe1
Date: 2014-09-22 18:15 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/dbbcbc97abe1/

Log:    Two performance optimizations in strategies. Added test.

diff --git a/rstrategies.py b/rstrategies.py
--- a/rstrategies.py
+++ b/rstrategies.py
@@ -28,20 +28,22 @@
             if hasattr(strategy_class, "_is_strategy") and 
strategy_class._is_strategy:
                 strategy_class._strategy_instance = 
self.instantiate_empty(strategy_class)
                 self.strategies.append(strategy_class)
-            
-            # Patch root class: Add default handler for visitor
-            def copy_from_OTHER(self, other):
-                self.copy_from(other)
-            funcname = "copy_from_" + strategy_class.__name__
-            copy_from_OTHER.func_name = funcname
-            setattr(root_class, funcname, copy_from_OTHER)
-            
-            # Patch strategy class: Add polymorphic visitor function
-            def initiate_copy_into(self, other):
-                getattr(other, funcname)(self)
-            strategy_class.initiate_copy_into = initiate_copy_into
+            self.patch_strategy_class(strategy_class, root_class)
         self.order_strategies()
     
+    def patch_strategy_class(self, strategy_class, root_class):
+        # Patch root class: Add default handler for visitor
+        def copy_from_OTHER(self, other):
+            self.copy_from(other)
+        funcname = "copy_from_" + strategy_class.__name__
+        copy_from_OTHER.func_name = funcname
+        setattr(root_class, funcname, copy_from_OTHER)
+        
+        # Patch strategy class: Add polymorphic visitor function
+        def initiate_copy_into(self, other):
+            getattr(other, funcname)(self)
+        strategy_class.initiate_copy_into = initiate_copy_into
+    
     def decorate_strategies(self, transitions):
         "NOT_RPYTHON"
         for strategy_class, generalized in transitions.items():
@@ -178,8 +180,8 @@
         return False
     
 class SingleValueStrategy(AbstractStrategy):
-    _immutable_fields_ = ["_size", "val"]
-    _attrs_ = ["_size", "val"]
+    _immutable_fields_ = ["_size"]
+    _attrs_ = ["_size"]
     # == Required:
     # See AbstractStrategy
     # check_index_*(...) - use mixin SafeIndexingMixin or UnsafeIndexingMixin
@@ -187,19 +189,18 @@
     
     def init_strategy(self, initial_size):
         self._size = initial_size
-        self.val = self.value()
     def fetch(self, index0):
         self.check_index_fetch(index0)
-        return self.val
+        return self.value()
     def store(self, index0, value):
         self.check_index_store(index0)
-        if self.val is value:
+        if self.value() is value:
             return
         self.cannot_handle_value(index0, value)
     def size(self):
         return self._size
     def check_can_handle(self, value):
-        return value is self.val
+        return value is self.value()
     
 # ============== Basic strategies with storage ==============
 
diff --git a/spyvm/storage.py b/spyvm/storage.py
--- a/spyvm/storage.py
+++ b/spyvm/storage.py
@@ -36,7 +36,7 @@
 class AbstractStorageShadow(AbstractShadow):
     repr_classname = "AbstractStorageShadow"
     _attrs_ = []
-    import_from_mixin(rstrat.SafeIndexingMixin)
+    import_from_mixin(rstrat.UnsafeIndexingMixin)
     
     def __init__(self, space, w_self, size):
         AbstractShadow.__init__(self, space, w_self, size)
@@ -45,19 +45,20 @@
     def strategy_factory(self):
         return self.space.strategy_factory
     
-    def copy_from_AllNilStrategy(self, all_nil_storage):
+    def copy_from_AllNilStorageShadow(self, all_nil_storage):
         pass # Fields already initialized to nil
 
+    def default_value(self):
+        return self.space.w_nil
+
 @rstrat.strategy()
 class ListStorageShadow(AbstractStorageShadow):
     repr_classname = "ListStorageShadow"
     import_from_mixin(rstrat.GenericStrategy)
-    def default_value(self): return self.space.w_nil
 
 class WeakListStorageShadow(AbstractStorageShadow):
     repr_classname = "WeakListStorageShadow"
     import_from_mixin(rstrat.WeakGenericStrategy)
-    def default_value(self): return self.space.w_nil
 
 @rstrat.strategy(generalize=[ListStorageShadow])
 class SmallIntegerOrNilStorageShadow(AbstractStorageShadow):
@@ -66,7 +67,6 @@
     contained_type = model.W_SmallInteger
     def wrap(self, val): return self.space.wrap_int(val)
     def unwrap(self, w_val): return self.space.unwrap_int(w_val)
-    def default_value(self): return self.space.w_nil
     def wrapped_tagged_value(self): return self.space.w_nil
     def unwrapped_tagged_value(self): return constants.MAXINT
 
@@ -78,7 +78,6 @@
     tag_float = sys.float_info.max
     def wrap(self, val): return self.space.wrap_float(val)
     def unwrap(self, w_val): return self.space.unwrap_float(w_val)
-    def default_value(self): return self.space.w_nil
     def wrapped_tagged_value(self): return self.space.w_nil
     def unwrapped_tagged_value(self): return self.tag_float
 
diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py
--- a/spyvm/test/test_model.py
+++ b/spyvm/test/test_model.py
@@ -31,6 +31,10 @@
 def test_new_namedvars():
     w_mycls = bootstrap_class(3)
     w_myinstance = w_mycls.as_class_get_shadow(space).new()
+    
+    w_myinstance.store(space, 0, w_myinstance) # Make sure ListStorage is used
+    w_myinstance.store(space, 0, space.w_nil)
+    
     assert isinstance(w_myinstance, model.W_PointersObject)
     assert w_myinstance.getclass(space).is_same_object(w_mycls)
     assert w_myinstance.fetch(space, 0).is_nil(space)
diff --git a/spyvm/test/test_strategies.py b/spyvm/test/test_strategies.py
--- a/spyvm/test/test_strategies.py
+++ b/spyvm/test/test_strategies.py
@@ -55,6 +55,18 @@
     assert index_nil < index_float < index_list
     assert index_nil < index_int < index_list
 
+def test_optimized_strategy_switch(monkeypatch):
+    a = arr(5)
+    def copy_from(self, other):
+        assert False, "The default copy_from() routine should not be called!"
+    
+    monkeypatch.setattr(storage.AbstractStorageShadow, "copy_from", copy_from)
+    try:
+        s = a.shadow
+        s.strategy_factory().switch_strategy(s, 
storage.SmallIntegerOrNilStorageShadow)
+    finally:
+        monkeypatch.undo()
+    
 # ====== AllNil StorageShadow
 
 def test_EmptyArray():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to