Author: Anton Gulenko <anton.gule...@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 + +@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 +@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 +@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: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit