Author: Anton Gulenko <anton.gule...@googlemail.com> Branch: storage Changeset: r912:541b01ff2814 Date: 2014-07-14 20:22 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/541b01ff2814/
Log: Some fixes to storage strategies: - Added size parameter to each Shadow constructor - Optimized transitions between certain strategies. diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -693,7 +693,7 @@ old_shadow = self._get_shadow() shadow = old_shadow if not isinstance(old_shadow, TheClass): - shadow = TheClass(space, self) + shadow = TheClass(space, self, old_shadow.size()) self.switch_shadow(shadow) return shadow diff --git a/spyvm/plugins/bitblt.py b/spyvm/plugins/bitblt.py --- a/spyvm/plugins/bitblt.py +++ b/spyvm/plugins/bitblt.py @@ -727,8 +727,8 @@ _attrs_ = ["w_bits", "width", "height", "depth", "offsetX", "offsetY", "msb", "pixPerWord", "pitch", "invalid"] - def __init__(self, space, w_self): - AbstractCachingShadow.__init__(self, space, w_self) + def __init__(self, space, w_self, size): + AbstractCachingShadow.__init__(self, space, w_self, size) self.invalid = False def intOrIfNil(self, w_int, i): diff --git a/spyvm/primitives.py b/spyvm/primitives.py --- a/spyvm/primitives.py +++ b/spyvm/primitives.py @@ -1314,7 +1314,7 @@ # The block bytecodes are stored inline: so we skip past the # byteodes to invoke this primitive to find them (hence +2) initialip = s_frame.pc() + 2 - s_new_context = shadow.BlockContextShadow(interp.space, None, w_method_context, argcnt, initialip) + s_new_context = shadow.BlockContextShadow(interp.space, None, 0, w_method_context, argcnt, initialip) return s_new_context.w_self() @expose_primitive(VALUE, result_is_new_frame=True) diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -17,7 +17,7 @@ provides_getname = False repr_classname = "AbstractShadow" - def __init__(self, space, w_self): + def __init__(self, space, w_self, size): self.space = space assert w_self is None or isinstance(w_self, model.W_PointersObject) self._w_self = w_self @@ -64,7 +64,7 @@ _attrs_ = [] repr_classname = "AbstractStorageShadow" def __init__(self, space, w_self, size): - AbstractShadow.__init__(self, space, w_self) + AbstractShadow.__init__(self, space, w_self, size) def store(self, n0, w_val): if self.can_contain(w_val): return self.do_store(n0, w_val) @@ -79,6 +79,15 @@ raise NotImplementedError() def generalized_strategy_for(self, w_val): raise NotImplementedError() + + 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) class AllNilStorageShadow(AbstractStorageShadow): repr_classname = "AllNilStorageShadow" @@ -130,9 +139,6 @@ self.storage[n0] = self.nil_value else: self.storage[n0] = self.unwrap(self.space, w_val) - - def copy_from_AllNil(self, all_nil_storage): - pass # Already initialized # This is to avoid code duplication @objectmodel.specialize.arg(0) @@ -230,13 +236,6 @@ self.initialize_storage(size) def size(self): return len(self.storage) - def copy_from(self, other_shadow): - if self.size() != other_shadow.size(): - self.initialize_storage(other_shadow.size()) - for i in range(self.size()): - w_val = other_shadow.fetch(i) - if not w_val.is_nil(self.space): - self.store(i, w_val) class ListStorageShadow(AbstractStorageShadow): _attrs_ = ['storage'] @@ -273,8 +272,8 @@ import_from_mixin(version.VersionMixin) version = None - def __init__(self, space, w_self): - ListStorageShadow.__init__(self, space, w_self, 0) + def __init__(self, space, w_self, size): + ListStorageShadow.__init__(self, space, w_self, size) self.changed() # ____________________________________________________________ @@ -305,9 +304,9 @@ provides_getname = True repr_classname = "ClassShadow" - def __init__(self, space, w_self): + def __init__(self, space, w_self, size): self.subclass_s = {} - AbstractCachingShadow.__init__(self, space, w_self) + AbstractCachingShadow.__init__(self, space, w_self, size) def store(self, n0, w_val): AbstractCachingShadow.store(self, n0, w_val) @@ -425,7 +424,7 @@ def flush_method_caches(self): look_in_shadow = self while look_in_shadow is not None: - look_in_shadow.s_methoddict().sync_method_cache() + look_in_shadow.s_methoddict().flush_method_cache() look_in_shadow = look_in_shadow._s_superclass def new(self, extrasize=0): @@ -535,7 +534,7 @@ "NOT_RPYTHON" # this is only for testing. if self._s_methoddict is None: w_methoddict = model.W_PointersObject(self.space, None, 2) - w_methoddict.store(self.space, 1, model.W_PointersObject(self.space, None, 0)) + w_methoddict.store(self.space, constants.METHODDICT_VALUES_INDEX, model.W_PointersObject(self.space, None, 0)) self.store_s_methoddict(w_methoddict.as_methoddict_get_shadow(self.space)) self.s_methoddict().invalid = False @@ -553,11 +552,11 @@ _attrs_ = ['methoddict', 'invalid', 's_class'] repr_classname = "MethodDictionaryShadow" - def __init__(self, space, w_self): + def __init__(self, space, w_self, size): self.invalid = True self.s_class = None self.methoddict = {} - ListStorageShadow.__init__(self, space, w_self, 0) + ListStorageShadow.__init__(self, space, w_self, size) def update(self): self.sync_method_cache() @@ -567,7 +566,7 @@ return None # we may be invalid if Smalltalk code did not call flushCache return self.methoddict.get(w_selector, None) - # Remove update call for changes to ourselves: + # We do not call update() after changes to ourselves: # Whenever a method is added, it's keyword is added to w_self, then the # w_compiled_method is added to our observee. # sync_method_cache at this point would not have the desired effect, because in @@ -575,17 +574,30 @@ # its contents array is filled with the value belonging to the new key. def store(self, n0, w_value): ListStorageShadow.store(self, n0, w_value) - self.invalid = True - + if n0 == constants.METHODDICT_VALUES_INDEX: + self.setup_notification() + if n0 >= constants.METHODDICT_NAMES_INDEX: + self.invalid = True + + def setup_notification(self): + self.w_values().as_observed_get_shadow(self.space).notify(self) + + def w_values(self): + w_values = self.fetch(constants.METHODDICT_VALUES_INDEX) + assert isinstance(w_values, model.W_PointersObject) + return w_values + + def flush_method_cache(self): + # Lazy synchronization: Only flush the cache, if we are already synchronized. + if self.invalid: + self.sync_method_cache() + def sync_method_cache(self): if self.size() == 0: return - w_values = self.fetch(constants.METHODDICT_VALUES_INDEX) - assert isinstance(w_values, model.W_PointersObject) - s_values = w_values.as_observed_get_shadow(self.space) - s_values.notify(self) + self.methoddict = {} size = self.size() - constants.METHODDICT_NAMES_INDEX - self.methoddict = {} + w_values = self.w_values() for i in range(size): w_selector = self.w_self().fetch(self.space, constants.METHODDICT_NAMES_INDEX+i) if not w_selector.is_nil(self.space): @@ -614,12 +626,12 @@ _attrs_ = ['_w_self_size'] repr_classname = "AbstractRedirectingShadow" - def __init__(self, space, w_self): - AbstractShadow.__init__(self, space, w_self) + def __init__(self, space, w_self, size): if w_self is not None: self._w_self_size = w_self.size() else: - self._w_self_size = 0 + self._w_self_size = size + AbstractShadow.__init__(self, space, w_self, self._w_self_size) def size(self): return self._w_self_size @@ -641,9 +653,9 @@ # ______________________________________________________________________ # Initialization - def __init__(self, space, w_self): + def __init__(self, space, w_self, size=0): self._s_sender = None - AbstractRedirectingShadow.__init__(self, space, w_self) + AbstractRedirectingShadow.__init__(self, space, w_self, size) self.instances_w = {} def copy_field_from(self, n0, other_shadow): @@ -981,14 +993,14 @@ # === Initialization === - def __init__(self, space, w_self=None, w_home=None, argcnt=0, initialip=0): + def __init__(self, space, w_self=None, size=0, w_home=None, argcnt=0, initialip=0): self = jit.hint(self, access_directly=True, fresh_virtualizable=True) creating_w_self = w_self is None if creating_w_self: s_home = w_home.as_methodcontext_get_shadow(space) contextsize = s_home.size() - s_home.tempsize() w_self = model.W_PointersObject(space, space.w_BlockContext, contextsize) - ContextPartShadow.__init__(self, space, w_self) + ContextPartShadow.__init__(self, space, w_self, size) if creating_w_self: w_self.store_shadow(self) self.store_expected_argument_count(argcnt) @@ -1115,10 +1127,10 @@ # === Initialization === @jit.unroll_safe - def __init__(self, space, w_self=None, w_method=None, w_receiver=None, + def __init__(self, space, w_self=None, size=0, w_method=None, w_receiver=None, arguments=[], closure=None, pc=0): self = jit.hint(self, access_directly=True, fresh_virtualizable=True) - ContextPartShadow.__init__(self, space, w_self) + ContextPartShadow.__init__(self, space, w_self, size) self.store_w_receiver(w_receiver) self.store_pc(pc) self.closure = closure @@ -1280,8 +1292,8 @@ class ObserveeShadow(ListStorageShadow): _attrs_ = ['dependent'] repr_classname = "ObserveeShadow" - def __init__(self, space, w_self): - ListStorageShadow.__init__(self, space, w_self, 0) + def __init__(self, space, w_self, size): + ListStorageShadow.__init__(self, space, w_self, size) self.dependent = None def store(self, n0, w_value): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit