[pypy-commit] lang-smalltalk rstrategies: Implementing rstrategies
anton_gulenko
noreply at buildbot.pypy.org
Thu Aug 21 12:54:52 CEST 2014
Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: rstrategies
Changeset: r1036:d7e93bfe0dd6
Date: 2014-08-20 16:12 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/d7e93bfe0dd6/
Log: Implementing rstrategies
diff --git a/rstrategies.py b/rstrategies.py
--- a/rstrategies.py
+++ b/rstrategies.py
@@ -2,15 +2,23 @@
import weakref
from rpython.rlib import jit
+def collect_subclasses(cls):
+ "NOT_RPYTHON"
+ subclasses = []
+ for subcls in cls.__subclasses__():
+ subclasses.append(subcls)
+ subclasses.extend(collect_subclasses(subcls))
+ return subclasses
+
class StrategyFactory(object):
- _immutable_fields_ = ["strategies[*]"]
+ _immutable_fields_ = ["xx[*]"]
- def __init__(self, strategy_root_class, transitions):
- self.strategies = []
- self.root_class = strategy_root_class
+ def __init__(self, root_class, all_strategy_classes=None):
+ if all_strategy_classes is None:
+ all_strategy_classes = collect_subclasses(root_class)
+ self.strategies = all_strategy_classes
- for strategy_class, generalized in transitions.items():
- self.strategies.append(strategy_class)
+ for strategy_class in self.strategies:
strategy_class._strategy_instance = self.instantiate_empty(strategy_class)
# Patch root class: Add default handler for visitor
@@ -18,14 +26,17 @@
self.copy_from(other)
funcname = "copy_from_" + strategy_class.__name__
copy_from_OTHER.func_name = funcname
- setattr(self.root_class, funcname, copy_from_OTHER)
+ 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.create_transition(strategy_class, generalized)
+
+ def setup_strategy_transitions(self, transitions):
+ "NOT_RPYTHON"
+ for strategy_class, generalized in transitions.items():
+ generalize(generalized)(strategy_class)
# Instantiate new_strategy_type with size, replace old_strategy with it,
# and return the new instance
@@ -39,6 +50,7 @@
def switch_strategy(self, old_strategy, new_strategy_type):
new_instance = self.instantiate_and_switch(old_strategy, old_strategy.size(), new_strategy_type)
old_strategy.initiate_copy_into(new_instance)
+ new_instance.strategy_switched()
return new_instance
@jit.unroll_safe
@@ -55,6 +67,7 @@
for i, strategy_type in enumerate(self.strategies):
if can_handle[i]:
return strategy_type
+ raise Exception("Could not find strategy to handle: %s" % objects)
def cannot_handle_value(self, old_strategy, index0, value):
strategy_type = old_strategy.generalized_strategy_for(value)
@@ -64,24 +77,44 @@
def _freeze_(self):
# Instance will be frozen at compile time, making accesses constant.
return True
-
- def create_transition(self, strategy_class, generalized):
+
+def generalize(generalized):
+ def decorator(strategy_class):
# Patch strategy class: Add generalized_strategy_for
+ # TODO - optimize this method
+ @jit.unroll_safe
def generalized_strategy_for(self, value):
for strategy in generalized:
if strategy._strategy_instance.check_can_handle(value):
return strategy
raise Exception("Could not find generalized strategy for %s coming from %s" % (value, self))
strategy_class.generalized_strategy_for = generalized_strategy_for
+ return strategy_class
+ return decorator
+
+class AbstractCollection(object):
+ # == Required:
+ # store(self, n0, e)
+
+ def strategy_switched(self): pass
+ def init_strategy(self, initial_size): pass
+
+ def initiate_copy_into(self, other):
+ other.copy_from(self)
+
+ def copy_from(self, other):
+ assert self.size() == other.size()
+ for i in range(self.size()):
+ self.copy_field_from(i, other)
+
+ def copy_field_from(self, n0, other):
+ self.store(n0, other.fetch(n0))
class AbstractStrategy(object):
# == Required:
# strategy_factory(self) - Access to StorageFactory
# __init__(...) - Constructor should invoke the provided init_strategy(self, size) method
- def init_strategy(self, initial_size):
- pass
-
def store(self, index0, value):
raise NotImplementedError("Abstract method")
@@ -97,17 +130,6 @@
def cannot_handle_value(self, index0, value):
self.strategy_factory().cannot_handle_value(self, index0, value)
- def initiate_copy_into(self, other):
- other.copy_from(self)
-
- def copy_from(self, other):
- assert self.size() == other.size()
- for i in range(self.size()):
- self.copy_field_from(i, other)
-
- def copy_field_from(self, n0, other):
- self.store(n0, other.fetch(n0))
-
# ============== Special Strategies with no storage array ==============
class EmptyStrategy(AbstractStrategy):
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -611,12 +611,6 @@
assert shadow, "The shadow has not been initialized yet!"
return shadow
- def switch_shadow(self, new_shadow, w_element=None):
- old_shadow = self.assert_shadow()
- self.store_shadow(new_shadow)
- old_shadow.copy_into(new_shadow)
- new_shadow.attach_shadow()
-
def space(self):
return self.assert_shadow().space
@@ -675,7 +669,7 @@
def instsize(self):
return self.class_shadow(self.space()).instsize()
- def store_shadow(self, shadow, operation="", w_element=None, log_classname=True):
+ def store_shadow(self, shadow, operation="Switched", w_element=None, log_classname=True):
old_shadow = self.shadow
self.shadow = shadow
self.log_storage(operation, old_shadow, log_classname, w_element)
diff --git a/spyvm/plugins/bitblt.py b/spyvm/plugins/bitblt.py
--- a/spyvm/plugins/bitblt.py
+++ b/spyvm/plugins/bitblt.py
@@ -47,15 +47,13 @@
class BitBltShadow(AbstractCachingShadow):
+ repr_classname = "BitBltShadow"
WordSize = 32
MaskTable = [r_uint(0)]
for i in xrange(WordSize):
MaskTable.append(r_uint((2 ** (i + 1)) - 1))
AllOnes = r_uint(0xFFFFFFFF)
- def attach_shadow(self):
- pass
-
def intOrIfNil(self, w_int, i):
return intOrIfNil(self.space, w_int, i)
@@ -724,6 +722,7 @@
class FormShadow(AbstractCachingShadow):
+ repr_classname = "FormShadow"
_attrs_ = ["w_bits", "width", "height", "depth", "offsetX",
"offsetY", "msb", "pixPerWord", "pitch", "invalid"]
@@ -734,7 +733,7 @@
def intOrIfNil(self, w_int, i):
return intOrIfNil(self.space, w_int, i)
- def attach_shadow(self):
+ def strategy_switched(self):
self.invalid = True
if self.size() < 5:
return
diff --git a/spyvm/storage.py b/spyvm/storage.py
--- a/spyvm/storage.py
+++ b/spyvm/storage.py
@@ -1,5 +1,4 @@
-import weakref
from spyvm import model, version, constants
from spyvm.version import elidable_for_version
from rpython.rlib import objectmodel, jit
@@ -14,7 +13,8 @@
_immutable_fields_ = ['space']
provides_getname = False
repr_classname = "AbstractShadow"
-
+ import_from_mixin(rstrat.AbstractCollection)
+
def __init__(self, space, w_self, size):
self.space = space
assert w_self is None or isinstance(w_self, model.W_PointersObject)
@@ -29,35 +29,6 @@
else:
return "<%s>" % self.repr_classname
- def fetch(self, n0):
- raise NotImplementedError("Abstract class")
- def store(self, n0, w_value):
- raise NotImplementedError("Abstract class")
- def size(self):
- raise NotImplementedError("Abstract class")
-
- # This will invoke an appropriate copy_from_* method.
- # Overwriting this allows optimized transitions between certain storage types.
- def copy_into(self, other_shadow):
- other_shadow.copy_from(self)
-
- def attach_shadow(self): pass
-
- def copy_field_from(self, n0, other_shadow):
- self.store(n0, other_shadow.fetch(n0))
-
- def copy_from(self, other_shadow):
- assert self.size() == other_shadow.size()
- for i in range(self.size()):
- self.copy_field_from(i, other_shadow)
-
- def copy_from_AllNil(self, all_nil_storage):
- self.copy_from(all_nil_storage)
- def copy_from_SmallIntegerOrNil(self, small_int_storage):
- self.copy_from(small_int_storage)
- def copy_from_FloatOrNil(self, float_storage):
- self.copy_from(float_storage)
-
# ========== Storage classes implementing storage strategies ==========
class AbstractStorageShadow(AbstractShadow):
@@ -74,11 +45,17 @@
def copy_from_AllNilStrategy(self, all_nil_storage):
pass # Fields already initialized to nil
-class AllNilStorageShadow(AbstractStorageShadow):
- repr_classname = "AllNilStorageShadow"
- import_from_mixin(rstrat.SingleValueStrategy)
- def value(self): return self.space.w_nil
+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
+
+ at rstrat.generalize([ListStorageShadow])
class SmallIntegerOrNilStorageShadow(AbstractStorageShadow):
repr_classname = "SmallIntegerOrNilStorageShadow"
import_from_mixin(rstrat.TaggingStrategy)
@@ -89,6 +66,7 @@
def wrapped_tagged_value(self): return self.space.w_nil
def unwrapped_tagged_value(self): return constants.MAXINT
+ at rstrat.generalize([ListStorageShadow])
class FloatOrNilStorageShadow(AbstractStorageShadow):
repr_classname = "FloatOrNilStorageShadow"
import_from_mixin(rstrat.TaggingStrategy)
@@ -99,15 +77,14 @@
def wrapped_tagged_value(self): return self.space.w_nil
def unwrapped_tagged_value(self): import sys; return sys.float_info.max
-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
+ at rstrat.generalize([
+ SmallIntegerOrNilStorageShadow,
+ FloatOrNilStorageShadow,
+ ListStorageShadow])
+class AllNilStorageShadow(AbstractStorageShadow):
+ repr_classname = "AllNilStorageShadow"
+ import_from_mixin(rstrat.SingleValueStrategy)
+ def value(self): return self.space.w_nil
class StrategyFactory(rstrat.StrategyFactory):
_immutable_fields_ = ["space", "no_specialized_storage?"]
@@ -115,13 +92,7 @@
from spyvm import objspace
self.space = space
self.no_specialized_storage = objspace.ConstantFlag()
- rstrat.StrategyFactory.__init__(self, AbstractStorageShadow, {
- AllNilStorageShadow: [SmallIntegerOrNilStorageShadow,
- FloatOrNilStorageShadow,
- ListStorageShadow],
- SmallIntegerOrNilStorageShadow: [ListStorageShadow],
- FloatOrNilStorageShadow: [ListStorageShadow],
- })
+ rstrat.StrategyFactory.__init__(self, AbstractStorageShadow)
def strategy_type_for(self, objects, weak=False):
if weak:
@@ -141,7 +112,6 @@
w_self = old_strategy.w_self()
instance = strategy_class(self.space, w_self, size)
w_self.store_shadow(instance)
- instance.attach_shadow()
return instance
def instantiate_empty(self, strategy_type):
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
@@ -792,7 +792,7 @@
try:
monkeypatch.setattr(w_frame.shadow, "_sendSelfSelector", perform_mock)
- monkeypatch.setattr(bitblt.BitBltShadow, "attach_shadow", sync_cache_mock)
+ monkeypatch.setattr(bitblt.BitBltShadow, "strategy_switched", sync_cache_mock)
with py.test.raises(CallCopyBitsSimulation):
prim_table[primitives.BITBLT_COPY_BITS](interp, w_frame.as_context_get_shadow(space), argument_count-1)
finally:
More information about the pypy-commit
mailing list