[pypy-commit] lang-smalltalk rstrategies: Work in progress.
anton_gulenko
noreply at buildbot.pypy.org
Thu Aug 21 12:54:50 CEST 2014
Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: rstrategies
Changeset: r1035:4fd727366707
Date: 2014-08-03 13:29 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/4fd727366707/
Log: Work in progress.
diff --git a/rstrategies.py b/rstrategies.py
new file mode 100644
--- /dev/null
+++ b/rstrategies.py
@@ -0,0 +1,313 @@
+
+import weakref
+from rpython.rlib import jit
+
+class StrategyFactory(object):
+ _immutable_fields_ = ["strategies[*]"]
+
+ def __init__(self, strategy_root_class, transitions):
+ self.strategies = []
+ self.root_class = strategy_root_class
+
+ for strategy_class, generalized in transitions.items():
+ self.strategies.append(strategy_class)
+ strategy_class._strategy_instance = self.instantiate_empty(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(self.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)
+
+ # Instantiate new_strategy_type with size, replace old_strategy with it,
+ # and return the new instance
+ def instantiate_and_switch(self, old_strategy, size, new_strategy_type):
+ raise NotImplementedError("Abstract method")
+
+ # Return a functional but empty instance of strategy_type
+ def instantiate_empty(self, strategy_type):
+ raise NotImplementedError("Abstract method")
+
+ 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)
+ return new_instance
+
+ @jit.unroll_safe
+ def strategy_type_for(self, objects):
+ specialized_strategies = len(self.strategies)
+ can_handle = [True] * specialized_strategies
+ for obj in objects:
+ if specialized_strategies <= 1:
+ break
+ for i, strategy in enumerate(self.strategies):
+ if can_handle[i] and not strategy._strategy_instance.check_can_handle(obj):
+ can_handle[i] = False
+ specialized_strategies -= 1
+ for i, strategy_type in enumerate(self.strategies):
+ if can_handle[i]:
+ return strategy_type
+
+ def cannot_handle_value(self, old_strategy, index0, value):
+ strategy_type = old_strategy.generalized_strategy_for(value)
+ new_instance = self.switch_strategy(old_strategy, strategy_type)
+ new_instance.store(index0, value)
+
+ def _freeze_(self):
+ # Instance will be frozen at compile time, making accesses constant.
+ return True
+
+ def create_transition(self, strategy_class, generalized):
+ # Patch strategy class: Add generalized_strategy_for
+ 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
+
+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")
+
+ def fetch(self, index0):
+ raise NotImplementedError("Abstract method")
+
+ def size(self):
+ raise NotImplementedError("Abstract method")
+
+ def check_can_handle(self, value):
+ raise NotImplementedError("Abstract method")
+
+ 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):
+ # == Required:
+ # See AbstractStrategy
+
+ def fetch(self, index0):
+ raise IndexError
+ def store(self, index0, value):
+ self.cannot_handle_value(index0, value)
+ def size(self):
+ return 0
+ def check_can_handle(self, value):
+ return False
+
+class SingleValueStrategy(AbstractStrategy):
+ _immutable_fields_ = ["_size", "val"]
+ # == Required:
+ # See AbstractStrategy
+ # check_index_*(...) - use mixin SafeIndexingMixin or UnsafeIndexingMixin
+ # value(self) - the single value contained in this strategy
+
+ 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
+ def store(self, index0, value):
+ self.check_index_store(index0)
+ if self.val 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
+
+# ============== Basic strategies with storage ==============
+
+class StrategyWithStorage(AbstractStrategy):
+ _immutable_fields_ = ["storage"]
+ # == Required:
+ # See AbstractStrategy
+ # check_index_*(...) - use mixin SafeIndexingMixin, UnsafeIndexingMixin or VariableSizeMixin
+ # default_value(self) - The value to be initially contained in this strategy
+
+ def init_strategy(self, initial_size):
+ self.init_StrategyWithStorage(initial_size)
+
+ def init_StrategyWithStorage(self, initial_size):
+ default = self._unwrap(self.default_value())
+ self.storage = [default] * initial_size
+
+ def store(self, index0, wrapped_value):
+ self.check_index_store(index0)
+ if self.check_can_handle(wrapped_value):
+ unwrapped = self._unwrap(wrapped_value)
+ self.storage[index0] = unwrapped
+ else:
+ self.cannot_handle_value(index0, wrapped_value)
+
+ def fetch(self, index0):
+ self.check_index_fetch(index0)
+ unwrapped = self.storage[index0]
+ return self._wrap(unwrapped)
+
+ def _wrap(self, value):
+ raise NotImplementedError("Abstract method")
+
+ def _unwrap(self, value):
+ raise NotImplementedError("Abstract method")
+
+ def size(self):
+ return len(self.storage)
+
+class GenericStrategy(StrategyWithStorage):
+ # == Required:
+ # See StrategyWithStorage
+
+ def _wrap(self, value):
+ return value
+ def _unwrap(self, value):
+ return value
+ def check_can_handle(self, wrapped_value):
+ return True
+
+class WeakGenericStrategy(StrategyWithStorage):
+ # == Required:
+ # See StrategyWithStorage
+
+ def _wrap(self, value):
+ return value() or self.default_value()
+ def _unwrap(self, value):
+ assert value is not None
+ return weakref.ref(value)
+ def check_can_handle(self, wrapped_value):
+ return True
+
+# ============== Mixins for StrategyWithStorage ==============
+
+class SafeIndexingMixin(object):
+ def check_index_store(self, index0):
+ self.check_index(index0)
+ def check_index_fetch(self, index0):
+ self.check_index(index0)
+ def check_index(self, index0):
+ if index0 < 0 or index0 >= self.size():
+ raise IndexError
+
+class UnsafeIndexingMixin(object):
+ def check_index_store(self, index0):
+ pass
+ def check_index_fetch(self, index0):
+ pass
+
+class VariableSizeMixin(object):
+ # This can be used with StrategyWithStorage
+ # to add functionality for resizing the storage.
+ # Can be combined with either *IndexingMixin or *AutoresizeMixin
+
+ @jit.unroll_safe
+ def grow(self, by):
+ if by <= 0:
+ raise ValueError
+ for _ in range(by):
+ self.storage.append(self.default_value())
+
+ @jit.unroll_safe
+ def shrink(self, by):
+ if by <= 0:
+ raise ValueError
+ if by > self.size():
+ raise ValueError
+ for _ in range(by):
+ self.storage.pop()
+
+class SafeAutoresizeMixin(object):
+ def check_index_fetch(self, index0):
+ if index0 < 0 or index0 > self.size():
+ raise IndexError
+ def check_index_store(self, index0):
+ size = self.size()
+ if index0 < 0:
+ raise IndexError
+ if index0 >= size:
+ self.grow(index0 - size + 1)
+
+class UnsafeAutoresizeMixin(object):
+ def check_index_fetch(self, index0):
+ pass
+ def check_index_store(self, index0):
+ size = self.size()
+ if index0 >= size:
+ self.grow(index0 - size)
+
+# ============== Specialized Storage Strategies ==============
+
+class SpecializedStrategy(StrategyWithStorage):
+ # == Required:
+ # See StrategyWithStorage
+ # wrap(self, value) - Return a boxed object for the primitive value
+ # unwrap(self, value) - Return the unboxed primitive value of value
+
+ def _unwrap(self, value):
+ return self.unwrap(value)
+ def _wrap(self, value):
+ return self.wrap(value)
+
+class SingleTypeStrategy(SpecializedStrategy):
+ # == Required Functions:
+ # See SpecializedStrategy
+ # contained_type - The wrapped type that can be stored in this strategy
+
+ def check_can_handle(self, value):
+ return isinstance(value, self.contained_type)
+
+class TaggingStrategy(SingleTypeStrategy):
+ """This strategy uses a special tag value to represent a single additional object."""
+ # == Required:
+ # See SingleTypeStrategy
+ # wrapped_tagged_value(self) - The tagged object
+ # unwrapped_tagged_value(self) - The unwrapped tag value representing the tagged object
+
+ def init_strategy(self, initial_size):
+ self.tag = self.unwrapped_tagged_value()
+ self.w_tag = self.wrapped_tagged_value()
+ self.init_StrategyWithStorage(initial_size)
+
+ def check_can_handle(self, value):
+ return value is self.w_tag or \
+ (isinstance(value, self.contained_type) and \
+ self.unwrap(value) != self.tag)
+
+ def _unwrap(self, value):
+ if value is self.w_tag:
+ return self.tag
+ return self.unwrap(value)
+
+ def _wrap(self, value):
+ if value == self.tag:
+ return self.w_tag
+ return self.wrap(value)
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -578,10 +578,8 @@
self.initialize_storage(space, size, weak)
def initialize_storage(self, space, size, weak=False):
- from spyvm.storage import empty_storage
- storage = empty_storage(space, self, size, weak)
- self.store_shadow(storage)
- self.log_storage("Initialized")
+ storage = space.strategy_factory.empty_storage(self, size, weak)
+ self.store_shadow(storage, operation="Initialized")
def fillin(self, space, g_self):
W_AbstractObjectWithClassReference.fillin(self, space, g_self)
@@ -589,12 +587,10 @@
for g_obj in g_self.pointers:
g_obj.fillin(space)
pointers = g_self.get_pointers()
- # TODO -- Also handle weak objects loaded from images.
- from spyvm.storage import find_storage_for_objects
- storage = find_storage_for_objects(space, pointers, g_self.isweak())(space, self, len(pointers))
- self.store_shadow(storage)
+ storage_type = space.strategy_factory.strategy_type_for(pointers, g_self.isweak())
+ storage = storage_type(space, self, len(pointers))
+ self.store_shadow(storage, operation="Filledin", log_classname=False)
self.store_all(space, pointers)
- self.log_storage("Filledin", log_classname=False)
def is_weak(self):
from storage import WeakListStorageShadow
@@ -620,12 +616,6 @@
self.store_shadow(new_shadow)
old_shadow.copy_into(new_shadow)
new_shadow.attach_shadow()
- self.log_storage("Switched", old_shadow, w_element=w_element)
-
- def store_with_new_storage(self, new_storage, n0, w_val):
- space = self.space()
- self.switch_shadow(new_storage(space, self, self.size()), w_element=w_val)
- self.store(space, n0, w_val)
def space(self):
return self.assert_shadow().space
@@ -685,8 +675,10 @@
def instsize(self):
return self.class_shadow(self.space()).instsize()
- def store_shadow(self, shadow):
+ def store_shadow(self, shadow, operation="", w_element=None, log_classname=True):
+ old_shadow = self.shadow
self.shadow = shadow
+ self.log_storage(operation, old_shadow, log_classname, w_element)
def _get_shadow(self):
return self.shadow
@@ -696,8 +688,7 @@
old_shadow = self._get_shadow()
shadow = old_shadow
if not isinstance(old_shadow, TheClass):
- shadow = TheClass(space, self, old_shadow.size())
- self.switch_shadow(shadow)
+ shadow = space.strategy_factory.switch_strategy(old_shadow, TheClass)
return shadow
def get_shadow(self, space):
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -1,6 +1,6 @@
import os
-from spyvm import constants, model, model_display, wrapper, version, display
+from spyvm import constants, model, model_display, wrapper, version, display, storage
from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError
from rpython.rlib import jit, rpath
from rpython.rlib.objectmodel import instantiate, specialize, import_from_mixin
@@ -66,6 +66,7 @@
w_nil.w_class = None
self.add_bootstrap_object("w_nil", w_nil)
+ self.strategy_factory = storage.StrategyFactory(self)
self.make_bootstrap_classes()
self.make_bootstrap_objects()
diff --git a/spyvm/storage.py b/spyvm/storage.py
--- a/spyvm/storage.py
+++ b/spyvm/storage.py
@@ -1,9 +1,10 @@
-import sys, weakref
+import weakref
from spyvm import model, version, constants
from spyvm.version import elidable_for_version
from rpython.rlib import objectmodel, jit
from rpython.rlib.objectmodel import import_from_mixin
+import rstrategies as rstrat
class AbstractShadow(object):
"""A shadow is an optional extra bit of information that
@@ -60,211 +61,94 @@
# ========== Storage classes implementing storage strategies ==========
class AbstractStorageShadow(AbstractShadow):
- _attrs_ = []
repr_classname = "AbstractStorageShadow"
+ import_from_mixin(rstrat.SafeIndexingMixin)
- def store(self, n0, w_val):
- if self.can_contain(w_val):
- return self.do_store(n0, w_val)
- new_storage = self.generalized_strategy_for(w_val)
- return self._w_self.store_with_new_storage(new_storage, n0, w_val)
- def can_contain(self, w_val):
- return self.static_can_contain(self.space, w_val)
- @staticmethod
- def static_can_contain(space, w_val):
- raise NotImplementedError()
- def do_store(self, n0, w_val):
- raise NotImplementedError()
- def generalized_strategy_for(self, w_val):
- raise NotImplementedError()
+ def __init__(self, space, w_self, size):
+ AbstractShadow.__init__(self, space, w_self, size)
+ self.init_strategy(size)
- def copy_from_AllNil(self, all_nil_storage):
- pass # Already initialized
- def copy_from(self, other_shadow):
- assert self.size() == other_shadow.size()
- for i in range(self.size()):
- w_val = other_shadow.fetch(i)
- if not w_val.is_nil(self.space): # nil fields already initialized
- self.store(i, w_val)
+ def strategy_factory(self):
+ return self.space.strategy_factory
+
+ def copy_from_AllNilStrategy(self, all_nil_storage):
+ pass # Fields already initialized to nil
class AllNilStorageShadow(AbstractStorageShadow):
repr_classname = "AllNilStorageShadow"
- _attrs_ = ['_size']
- _immutable_fields_ = ['_size']
- def __init__(self, space, w_self, size):
- AbstractStorageShadow.__init__(self, space, w_self, size)
- self._size = size
- def fetch(self, n0):
- if n0 >= self._size:
- raise IndexError
- return self.space.w_nil
- def copy_into(self, other_shadow):
- other_shadow.copy_from_AllNil(self)
- def do_store(self, n0, w_value):
- pass
- def size(self):
- return self._size
- def generalized_strategy_for(self, w_val):
- return find_storage_for_objects(self.space, [w_val])
- @staticmethod
- def static_can_contain(space, w_val):
- return isinstance(w_val, model.W_Object) and w_val.is_nil(space)
-
-class AbstractValueOrNilStorageMixin(object):
- # Class must provide: wrap, unwrap, nil_value, is_nil_value, wrapper_class
- _attrs_ = ['storage']
- _immutable_fields_ = ['storage']
-
- def __init__(self, space, w_self, size):
- AbstractStorageShadow.__init__(self, space, w_self, size)
- self.storage = [self.nil_value] * size
-
- def size(self):
- return len(self.storage)
-
- def generalized_strategy_for(self, w_val):
- return ListStorageShadow
-
- def fetch(self, n0):
- val = self.storage[n0]
- if self.is_nil_value(val):
- return self.space.w_nil
- else:
- return self.wrap(self.space, val)
-
- def do_store(self, n0, w_val):
- if w_val.is_nil(self.space):
- self.storage[n0] = self.nil_value
- else:
- self.storage[n0] = self.unwrap(self.space, w_val)
-
-# This is to avoid code duplication
- at objectmodel.specialize.arg(0)
-def _value_or_nil_can_handle(cls, space, w_val):
- return isinstance(w_val, model.W_Object) and w_val.is_nil(space) or \
- (isinstance(w_val, cls.wrapper_class) \
- and not cls.is_nil_value(cls.unwrap(space, w_val)))
+ import_from_mixin(rstrat.SingleValueStrategy)
+ def value(self): return self.space.w_nil
class SmallIntegerOrNilStorageShadow(AbstractStorageShadow):
repr_classname = "SmallIntegerOrNilStorageShadow"
- nil_value = constants.MAXINT
- wrapper_class = model.W_SmallInteger
- import_from_mixin(AbstractValueOrNilStorageMixin)
-
- @staticmethod
- def static_can_contain(space, w_val):
- return _value_or_nil_can_handle(SmallIntegerOrNilStorageShadow, space, w_val)
- @staticmethod
- def is_nil_value(val):
- return val == SmallIntegerOrNilStorageShadow.nil_value
- @staticmethod
- def wrap(space, val):
- return space.wrap_int(val)
- @staticmethod
- def unwrap(space, w_val):
- return space.unwrap_int(w_val)
- def copy_into(self, other_shadow):
- other_shadow.copy_from_SmallIntegerOrNil(self)
+ import_from_mixin(rstrat.TaggingStrategy)
+ 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
class FloatOrNilStorageShadow(AbstractStorageShadow):
repr_classname = "FloatOrNilStorageShadow"
- nil_value = sys.float_info.max
- wrapper_class = model.W_Float
- import_from_mixin(AbstractValueOrNilStorageMixin)
-
- @staticmethod
- def static_can_contain(space, w_val):
- return _value_or_nil_can_handle(FloatOrNilStorageShadow, space, w_val)
- @staticmethod
- def is_nil_value(val):
- return val == FloatOrNilStorageShadow.nil_value
- @staticmethod
- def wrap(space, val):
- return space.wrap_float(val)
- @staticmethod
- def unwrap(space, w_val):
- return space.unwrap_float(w_val)
- def copy_into(self, other_shadow):
- other_shadow.copy_from_FloatOrNil(self)
-
-def empty_storage(space, w_self, size, weak=False):
- if weak:
- return WeakListStorageShadow(space, w_self, size)
- if space.no_specialized_storage.is_set():
- return ListStorageShadow(space, w_self, size)
- return AllNilStorageShadow(space, w_self, size)
-
- at jit.unroll_safe
-def find_storage_for_objects(space, vars, weak=False):
- if weak:
- return WeakListStorageShadow
- if space.no_specialized_storage.is_set():
- return ListStorageShadow
- 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 AllNilStorageShadow.static_can_contain(space, w_obj):
- all_nil_can_handle = False
- specialized_strategies = specialized_strategies - 1
- if small_int_can_handle and not SmallIntegerOrNilStorageShadow.static_can_contain(space, w_obj):
- small_int_can_handle = False
- specialized_strategies = specialized_strategies - 1
- if float_can_handle and not FloatOrNilStorageShadow.static_can_contain(space, w_obj):
- float_can_handle = False
- specialized_strategies = specialized_strategies - 1
-
- if specialized_strategies <= 0:
- return ListStorageShadow
-
- if all_nil_can_handle:
- return AllNilStorageShadow
- if small_int_can_handle:
- return SmallIntegerOrNilStorageShadow
- if float_can_handle:
- return FloatOrNilStorageShadow
-
- # If this happens, please look for a bug in the code above.
- assert False, "No strategy could be found for list..."
-
-class ListStorageMixin(object):
- def __init__(self, space, w_self, size):
- AbstractStorageShadow.__init__(self, space, w_self, size)
- self.initialize_storage(size)
- def size(self):
- return len(self.storage)
+ import_from_mixin(rstrat.TaggingStrategy)
+ contained_type = model.W_Float
+ 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): import sys; return sys.float_info.max
class ListStorageShadow(AbstractStorageShadow):
- _attrs_ = ['storage']
- _immutable_fields_ = ['storage']
repr_classname = "ListStorageShadow"
- import_from_mixin(ListStorageMixin)
-
- def initialize_storage(self, size):
- self.storage = [self.space.w_nil] * size
- def fetch(self, n0):
- return self.storage[n0]
- def store(self, n0, w_value):
- self.storage[n0] = w_value
+ import_from_mixin(rstrat.GenericStrategy)
+ def default_value(self): return self.space.w_nil
class WeakListStorageShadow(AbstractStorageShadow):
- _attrs_ = ['storage']
- _immutable_fields_ = ['storage']
repr_classname = "WeakListStorageShadow"
- import_from_mixin(ListStorageMixin)
+ import_from_mixin(rstrat.WeakGenericStrategy)
+ def default_value(self): return self.space.w_nil
- def initialize_storage(self, size):
- self.storage = [weakref.ref(self.space.w_nil)] * size
- def fetch(self, n0):
- weakobj = self.storage[n0]
- return weakobj() or self.space.w_nil
- def store(self, n0, w_value):
- assert w_value is not None
- self.storage[n0] = weakref.ref(w_value)
-
+class StrategyFactory(rstrat.StrategyFactory):
+ _immutable_fields_ = ["space", "no_specialized_storage?"]
+ def __init__(self, space):
+ 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],
+ })
+
+ def strategy_type_for(self, objects, weak=False):
+ if weak:
+ WeakListStorageShadow
+ if self.no_specialized_storage.is_set():
+ return ListStorageShadow
+ return rstrat.StrategyFactory.strategy_type_for(self, objects)
+
+ def empty_storage(self, w_self, size, weak=False):
+ if weak:
+ return WeakListStorageShadow(self.space, w_self, size)
+ if self.no_specialized_storage.is_set():
+ return ListStorageShadow(self.space, w_self, size)
+ return AllNilStorageShadow(self.space, w_self, size)
+
+ def instantiate_and_switch(self, old_strategy, size, strategy_class):
+ 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):
+ return strategy_type(self.space, None, 0)
+
# ========== Other storage classes, non-strategies ==========
-
+
class AbstractRedirectingShadow(AbstractShadow):
_attrs_ = ['_w_self_size']
repr_classname = "AbstractRedirectingShadow"
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -129,7 +129,7 @@
elif arg in ["--hacks"]:
space.run_spy_hacks.activate()
elif arg in ["-S"]:
- space.no_specialized_storage.activate()
+ space.strategy_factory.no_specialized_storage.activate()
elif arg in ["-u"]:
from spyvm.plugins.vmdebugging import stop_ui_process
stop_ui_process()
More information about the pypy-commit
mailing list