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