Author: Anton Gulenko <[email protected]>
Branch: strategies-tagging
Changeset: r680:74e7f1232b64
Date: 2014-03-20 17:37 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/74e7f1232b64/

Log:    Generalized TaggingStrategy to ValueOrNilStrategy, added strategy
        for floats. Small renamings and refactorings.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -644,10 +644,10 @@
     
     @jit.unroll_safe
     def __init__(self, space, w_class, size):
-        from spyvm.strategies import strategy_of_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 = strategy_of_size(self.s_class, size)
+        self.strategy = empty_strategy(self.s_class)
         self.initialize_storage(space, size)
         self.log_strategy_operation("Initialized")
     
diff --git a/spyvm/strategies.py b/spyvm/strategies.py
--- a/spyvm/strategies.py
+++ b/spyvm/strategies.py
@@ -1,7 +1,8 @@
 
 import sys
-from spyvm import model, shadow
+from spyvm import model, shadow, constants
 from rpython.rlib.objectmodel import import_from_mixin
+from rpython.rlib.rfloat import string_to_float
 
 # Disables all optimized strategies, for debugging.
 only_list_storage = False
@@ -20,9 +21,17 @@
     def set_storage_copied_from(self, space, w_obj, w_source_obj, 
reuse_storage=False):
         raise NotImplementedError("Abstract base class")
     
+    def store(self, space, w_obj, n0, w_val):
+        if self.can_contain(space, w_val):
+            self.do_store(space, w_obj, n0, w_val)
+        new_strategy = find_strategy_for_object(w_val)
+        return w_obj.store_with_new_strategy(space, new_strategy, n0, w_val)
+    
+    def can_contain(self, space, w_val):
+        raise NotImplementedError("Abstract base class")
     def fetch(self, space, w_obj, n0):
         raise NotImplementedError("Abstract base class")
-    def store(self, space, w_obj, n0, w_val):
+    def do_store(self, space, w_obj, n0, w_val):
         raise NotImplementedError("Abstract base class")
 
 class AbstractListStorageStrategy(AbstractStorageStrategy):
@@ -85,17 +94,12 @@
     __metaclass__ = SingletonMeta
     strategy_tag = 'allnil'
     
+    def can_contain(self, space, w_obj):
+        return w_obj == model.w_nil
     def fetch(self, space, w_obj, n0):
         return model.w_nil
-    
-    def store(self, space, w_obj, n0, w_val):
-        # This is an important moment, where we decide where to go on the 
first non-nil store.
-        if w_val == model.w_nil:
-            return
-        if not only_list_storage:
-            if TaggingSmallIntegerStorageStrategy.can_contain(w_val):
-                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 do_store(self, space, w_obj, n0, w_val):
+        pass
         
     def set_initial_storage(self, space, w_obj, size):
         pass
@@ -111,9 +115,11 @@
     __metaclass__ = SingletonMeta
     strategy_tag = 'list'
     
+    def can_contain(self, space, w_val):
+        return True
     def fetch(self, space, w_obj, n0):
         return self.storage(w_obj)[n0]
-    def store(self, space, w_obj, n0, w_val):
+    def do_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 initial_storage(self, space, size):
@@ -124,56 +130,90 @@
         length = w_obj.basic_size()
         return [w_obj.strategy.fetch(space, w_obj, i) for i in range(length)]
 
-class TaggingSmallIntegerStorageStrategy(AbstractIntStorageStrategy):
-    __metaclass__ = SingletonMeta
-    strategy_tag = 'tagging-smallint'
+class AbstractValueOrNilStorageStrategy(AbstractIntStorageStrategy):
     needs_objspace = True
+    strategy_tag = 'abstract-valueOrNil'
     
-    @staticmethod
-    def wrap(val):
-        return val << 1
-    @staticmethod
-    def unwrap(val):
-        return val >> 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 can_contain(self, space, w_val):
+        return w_val == model.w_nil or (isinstance(w_val, self.wrapper_class) 
and self.unwrap(space, w_val) != self.nil_value)
     
     def fetch(self, space, w_obj, n0):
         val = self.storage(w_obj)[n0]
         if val == self.nil_value:
             return space.w_nil
         else:
-            return space.wrap_int(self.unwrap(val))
+            return self.wrap(space, val)
         
-    def store(self, space, w_obj, n0, w_val):
+    def do_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))
+        if w_val == space.w_nil:
+                store[n0] = self.nil_value
         else:
-            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)
-        
+            store[n0] = self.unwrap(space, w_val)
+    
     def initial_storage(self, space, size):
         return [self.nil_value] * size
-    
+        
     def storage_for_list(self, space, collection):
         length = len(collection)
-        store = [self.nil_value] * length
+        store = self.initial_storage(length)
         for i in range(length):
             if collection[i] != space.w_nil:
-                store[i] = self.wrap(space.unwrap_int(collection[i]))
+                store[i] = self.unwrap(space, collection[i])
         return store
 
-def strategy_of_size(s_containing_class, size):
+class SmallIntegerOrNilStorageStrategy(AbstractValueOrNilStorageStrategy):
+    __metaclass__ = SingletonMeta
+    strategy_tag = 'float-orNil'
+    nil_value = constants.MAXINT
+    wrapper_class = model.W_SmallInteger
+    def wrap(self, space, val): return space.wrap_int(val)
+    def unwrap(self, space, w_val): return space.unwrap_int(w_val)
+
+class FloatOrNilStorageStrategy(AbstractValueOrNilStorageStrategy):
+    __metaclass__ = SingletonMeta
+    strategy_tag = 'smallint-orNil'
+    nil_value = string_to_float("-nan")
+    wrapper_class = model.W_Float
+    def wrap(self, space, val): return space.wrap_float(val)
+    def unwrap(self, space, w_val): return space.unwrap_float(w_val)
+
+def find_strategy_for_object(space, var):
+    return find_strategy_for_objects(space, [var])
+
+def find_strategy_for_objects(space, vars):
+    if only_list_storage:
+        ListStorageStrategy.singleton
+    
+    specialized_strategies = 3
+    all_nil_can_handle = True
+    small_int_can_handle = True
+    float_can_handle = True
+    for w_obj in vars:
+        if all_nil_can_handle and not 
AllNilStorageStrategy.singleton.can_contain(space, w_obj):
+            all_nil_can_handle = False
+            specialized_strategies = specialized_strategies - 1
+        if small_int_can_handle and not 
SmallIntegerOrNilStorageStrategy.singleton.can_contain(space, w_obj):
+            small_int_can_handle = False
+            specialized_strategies = specialized_strategies - 1
+        if float_can_handle and not 
FloatOrNilStorageStrategy.singleton.can_contain(space, w_obj):
+            float_can_handle = False
+            specialized_strategies = specialized_strategies - 1
+        
+        if specialized_strategies <= 0:
+            return ListStorageStrategy.singleton
+    
+    if all_nil_can_handle:
+        return AllNilStorageStrategy.singleton
+    if small_int_can_handle:
+        return SmallIntegerOrNilStorageStrategy.singleton
+    if float_can_handle:
+        return FloatOrNilStorageStrategy.singleton
+    
+    # If this happens, please look for a bug in the code above.
+    assert False, "No strategy could be found for list %r" % vars
+
+def empty_strategy(s_containing_class):
     if s_containing_class is None:
         # This is a weird and rare special case for w_nil
         return ListStorageStrategy.singleton
@@ -194,19 +234,7 @@
         # Ths class object shadows are not yet synchronized.
         return ListStorageStrategy.singleton
     
-    if not is_variable or only_list_storage:
+    if is_variable:
+        return find_strategy_for_objects(s_containing_class.space, vars)
+    else:
         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 AllNilStorageStrategy.singleton
-    else:
-        return TaggingSmallIntegerStorageStrategy.singleton
-    
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to