Author: Hubert Hesse <hubert.he...@student.hpi.uni-potsdam.de> Branch: 64bit-c2 Changeset: r796:e6c406381c28 Date: 2014-04-24 14:41 +0200 http://bitbucket.org/pypy/lang-smalltalk/changeset/e6c406381c28/
Log: Merged default diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -12,3 +12,5 @@ versions coglinux *.orig +spy-*.log +SDL.dll diff --git a/spyvm/model.py b/spyvm/model.py --- a/spyvm/model.py +++ b/spyvm/model.py @@ -15,12 +15,14 @@ that create W_PointersObjects of correct size with attached shadows. """ import sys, weakref -from spyvm import constants, error, system +from spyvm import constants, error, version, system +from spyvm.version import elidable_for_version from rpython.rlib import rrandom, objectmodel, jit, signature from rpython.rlib.rarithmetic import intmask, r_uint32, r_uint, r_int +from rpython.rlib.debug import make_sure_not_resized from rpython.tool.pairtype import extendabletype -from rpython.rlib.objectmodel import instantiate, compute_hash +from rpython.rlib.objectmodel import instantiate, compute_hash, import_from_mixin from rpython.rtyper.lltypesystem import lltype, rffi from rsdl import RSDL, RSDL_helper @@ -448,7 +450,7 @@ def __str__(self): if isinstance(self, W_PointersObject) and self.has_shadow(): - return self._shadow.getname() + return self._get_shadow().getname() else: name = None if self.has_class(): @@ -488,15 +490,20 @@ class W_AbstractPointersObject(W_AbstractObjectWithClassReference): """Common object.""" - _attrs_ = ['_shadow'] + _attrs_ = ['shadow'] + + def changed(self): + # This is invoked when an instance-variable is changed. + # Kept here in case it might be usefull in the future. + pass - _shadow = None # Default value + shadow = None # Default value @jit.unroll_safe def __init__(self, space, w_class, size): """Create new object with size = fixed + variable size.""" W_AbstractObjectWithClassReference.__init__(self, space, w_class) - self._shadow = None # Default value + self.store_shadow(None) def fillin(self, space, g_self): from spyvm.fieldtypes import fieldtypes_of @@ -514,12 +521,12 @@ def fetch(self, space, n0): if self.has_shadow(): - return self._shadow.fetch(n0) + return self._get_shadow().fetch(n0) return self._fetch(n0) def store(self, space, n0, w_value): if self.has_shadow(): - return self._shadow.store(n0, w_value) + return self._get_shadow().store(n0, w_value) return self._store(n0, w_value) def varsize(self, space): @@ -533,13 +540,17 @@ def size(self): if self.has_shadow(): - return self._shadow.size() + return self._get_shadow().size() return self.basic_size() def store_shadow(self, shadow): - assert self._shadow is None or self._shadow is shadow - self._shadow = shadow + assert self.shadow is None or self.shadow is shadow + self.shadow = shadow + self.changed() + def _get_shadow(self): + return self.shadow + @objectmodel.specialize.arg(2) def attach_shadow_of_class(self, space, TheClass): shadow = TheClass(space, self) @@ -549,7 +560,7 @@ @objectmodel.specialize.arg(2) def as_special_get_shadow(self, space, TheClass): - shadow = self._shadow + shadow = self._get_shadow() if not isinstance(shadow, TheClass): if shadow is not None: raise DetachingShadowError(shadow, TheClass) @@ -568,7 +579,7 @@ # Should only be used during squeak-image loading. def as_class_get_penumbra(self, space): from spyvm.shadow import ClassShadow - s_class = self._shadow + s_class = self._get_shadow() if s_class is None: s_class = ClassShadow(space, self) self.store_shadow(s_class) @@ -587,7 +598,7 @@ def as_context_get_shadow(self, space): from spyvm.shadow import ContextPartShadow # XXX TODO should figure out itself if its method or block context - if self._shadow is None: + if self._get_shadow() is None: if ContextPartShadow.is_block_context(self, space): return self.as_blockcontext_get_shadow(space) return self.as_methodcontext_get_shadow(space) @@ -606,17 +617,19 @@ return self.as_special_get_shadow(space, ObserveeShadow) def has_shadow(self): - return self._shadow is not None + return self._get_shadow() is not None def become(self, w_other): if not isinstance(w_other, W_AbstractPointersObject): return False # switching means also switching shadows - self._shadow, w_other._shadow = w_other._shadow, self._shadow + self.shadow, w_other.shadow = w_other.shadow, self.shadow # shadow links are in both directions -> also update shadows - if self.has_shadow(): self._shadow._w_self = self - if w_other.has_shadow(): w_other._shadow._w_self = w_other + if self.shadow is not None: self.shadow._w_self = self + if w_other.shadow is not None: w_other.shadow._w_self = w_other W_AbstractObjectWithClassReference._become(self, w_other) + self.changed() + w_other.changed() return True @jit.elidable @@ -633,24 +646,27 @@ from spyvm.fieldtypes import fieldtypes_of_length """Create new object with size = fixed + variable size.""" W_AbstractPointersObject.__init__(self, space, w_class, size) - vars = self._vars = [None] * size + vars = [None] * size + self.set_vars(vars) self.fieldtypes = fieldtypes_of_length(self.s_class, size) for i in range(size): # do it by hand for the JIT's sake vars[i] = w_nil - + + def set_vars(self, new_vars): + self._vars = new_vars + make_sure_not_resized(self._vars) + def fillin(self, space, g_self): W_AbstractPointersObject.fillin(self, space, g_self) from spyvm.fieldtypes import fieldtypes_of - self._vars = g_self.get_pointers() + self.set_vars(g_self.get_pointers()) self.fieldtypes = fieldtypes_of(self) def _fetch(self, n0): - # return self._vars[n0] fieldtypes = jit.promote(self.fieldtypes) return fieldtypes.fetch(self, n0) def _store(self, n0, w_value): - # self._vars[n0] = w_value fieldtypes = jit.promote(self.fieldtypes) return fieldtypes.store(self, n0, w_value) @@ -671,7 +687,7 @@ def clone(self, space): w_result = W_PointersObject(self.space, self.getclass(space), len(self._vars)) - w_result._vars = [self.fetch(space, i) for i in range(len(self._vars))] + w_result.set_vars([self.fetch(space, i) for i in range(len(self._vars))]) return w_result def fieldtype(self): @@ -996,6 +1012,8 @@ _attrs_ = ['pixelbuffer', '_realsize', '_real_depth_buffer', 'display', '_depth'] _immutable_fields_ = ['_realsize', 'display', '_depth', '_real_depth_buffer'] + pixelbuffer = None + @staticmethod def create(space, w_class, size, depth, display): if depth < 8: @@ -1202,11 +1220,11 @@ if len(self.literals) > 0: w_candidate = self.literals[-1] if isinstance(w_candidate, W_PointersObject): - c_shadow = w_candidate._shadow + c_shadow = w_candidate._get_shadow() if c_shadow is None and w_candidate.size() >= 2: w_class = w_candidate._fetch(1) if isinstance(w_class, W_PointersObject): - d_shadow = w_class._shadow + d_shadow = w_class._get_shadow() if isinstance(d_shadow, shadow.ClassShadow): classname = d_shadow.getname() elif isinstance(shadow, shadow.ClassShadow): 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, shadow, wrapper, system +from spyvm import constants, model, shadow, wrapper, system, version from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError from rpython.rlib import jit, rpath from rpython.rlib.objectmodel import instantiate, specialize @@ -79,7 +79,7 @@ w_Class = self.classtable["w_Class"] s_Metaclass = self.classtable["w_Metaclass"].as_class_get_penumbra(self) # XXX - proto_shadow = w_ProtoObjectClass._shadow + proto_shadow = w_ProtoObjectClass.shadow proto_shadow.store_w_superclass(w_Class) # at this point, all classes that still lack a w_class are themselves # metaclasses @@ -335,7 +335,7 @@ # XXX s = instantiate(shadow.ClassShadow) s.space = space - s.version = shadow.Version() + s.version = version.Version() s._w_self = w_class s.subclass_s = {} s._s_superclass = None diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -1,17 +1,10 @@ import weakref -from spyvm import model, constants, error, wrapper +from spyvm import model, constants, error, wrapper, version +from spyvm.version import elidable_for_version, constant_for_version from rpython.tool.pairtype import extendabletype from rpython.rlib import rarithmetic, jit - -def make_elidable_after_versioning(func): - @jit.elidable - def elidable_func(self, version, *args): - return func(self, *args) - def meth(self, *args): - jit.promote(self) - version = jit.promote(self.version) - return elidable_func(self, version, *args) - return meth +from rpython.rlib.objectmodel import import_from_mixin +from rpython.rlib.debug import make_sure_not_resized class AbstractShadow(object): """A shadow is an optional extra bit of information that @@ -38,10 +31,13 @@ class AbstractCachingShadow(AbstractShadow): _immutable_fields_ = ['version?'] _attrs_ = ['version'] + import_from_mixin(version.VersionMixin) + version = None + def __init__(self, space, w_self): AbstractShadow.__init__(self, space, w_self) - self.version = Version() + self.changed() def attach_shadow(self): self.w_self().store_shadow(self) @@ -59,11 +55,6 @@ AbstractShadow.store(self, n0, w_value) self.update() - def change(self): - self.version = Version() - -class Version: - pass # ____________________________________________________________ POINTERS = 0 @@ -87,7 +78,7 @@ _attrs_ = ["name", "_instance_size", "instance_varsized", "instance_kind", "_s_methoddict", "_s_superclass", "subclass_s"] - + def __init__(self, space, w_self): # fields added here should also be in objspace.py:56ff, 300ff self.name = '' @@ -263,12 +254,12 @@ " True if instances of this class have data stored as numerical bytes " return self.format == BYTES - @make_elidable_after_versioning + @constant_for_version def isvariable(self): " True if instances of this class have indexed inst variables " return self.instance_varsized - @make_elidable_after_versioning + @constant_for_version def instsize(self): " Number of named instance variables for each instance of this class " return self._instance_size @@ -293,7 +284,7 @@ del self.subclass_s[s_other] def changed(self): - self.superclass_changed(Version()) + self.superclass_changed(version.Version()) # this is done, because the class-hierarchy contains cycles def superclass_changed(self, version): @@ -308,7 +299,7 @@ def __repr__(self): return "<ClassShadow %s>" % (self.name or '?',) - @make_elidable_after_versioning + @constant_for_version def lookup(self, w_selector): look_in_shadow = self while look_in_shadow is not None: @@ -646,6 +637,7 @@ stacksize = self.stackend() - self.stackstart() tempsize = self.tempsize() self._temps_and_stack = [None] * (stacksize + tempsize) + make_sure_not_resized(self._temps_and_stack) for i in range(tempsize): self._temps_and_stack[i] = self.space.w_nil self._stack_ptr = rarithmetic.r_uint(tempsize) # we point after the last element @@ -1033,6 +1025,7 @@ "argsize", "islarge", "w_compiledin", "version"] _immutable_fields_ = ["version?", "_w_self"] + import_from_mixin(version.VersionMixin) def __init__(self, w_compiledmethod): self._w_self = w_compiledmethod @@ -1041,11 +1034,11 @@ def w_self(self): return self._w_self - @make_elidable_after_versioning + @constant_for_version def getliteral(self, index): return self.literals[index] - @make_elidable_after_versioning + @constant_for_version def compute_frame_size(self): # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 @@ -1058,7 +1051,7 @@ def update(self): w_compiledmethod = self._w_self - self.version = Version() + self.changed() self.bytecode = "".join(w_compiledmethod.bytes) self.bytecodeoffset = w_compiledmethod.bytecodeoffset() self.literalsize = w_compiledmethod.getliteralsize() @@ -1081,11 +1074,11 @@ association = wrapper.AssociationWrapper(None, w_association) self.w_compiledin = association.value() - @make_elidable_after_versioning + @constant_for_version def tempsize(self): return self._tempsize - @make_elidable_after_versioning + @constant_for_version def primitive(self): return self._primitive @@ -1095,26 +1088,20 @@ space, self, receiver, arguments, sender) return s_new - @make_elidable_after_versioning + @constant_for_version def getbytecode(self, pc): return self.bytecode[pc] class CachedObjectShadow(AbstractCachingShadow): + @elidable_for_version def fetch(self, n0): - jit.promote(self) - version = self.version - jit.promote(version) - return self.safe_fetch(n0, version) - - @jit.elidable - def safe_fetch(self, n0, version): - assert version is self.version return self._w_self._fetch(n0) def store(self, n0, w_value): - self.version = Version() - return self._w_self._store(n0, w_value) + res = self._w_self._store(n0, w_value) + self.changed() + return res def update(self): pass diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py --- a/spyvm/squeakimage.py +++ b/spyvm/squeakimage.py @@ -308,7 +308,7 @@ for chunk in self.chunks.itervalues(): casted = chunk.g_object.w_object if isinstance(casted, model.W_PointersObject) and casted.has_shadow(): - casted._shadow.update() + casted.shadow.update() def init_compactclassesarray(self): """ from the blue book (CompiledMethod Symbol Array PseudoContext LargePositiveInteger nil MethodDictionary Association Point Rectangle nil TranslatedMethod BlockContext MethodContext nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil ) """ diff --git a/spyvm/test/jittest/base.py b/spyvm/test/jittest/base.py --- a/spyvm/test/jittest/base.py +++ b/spyvm/test/jittest/base.py @@ -2,8 +2,8 @@ import os # TODO: -from pypy.tool.jitlogparser.parser import SimpleParser, Op -from pypy.tool.jitlogparser.storage import LoopStorage +from rpython.tool.jitlogparser.parser import SimpleParser, Op +from rpython.tool.jitlogparser.storage import LoopStorage from rpython.jit.metainterp.resoperation import opname from rpython.jit.tool import oparser diff --git a/spyvm/test/jittest/test_basic.py b/spyvm/test/jittest/test_basic.py --- a/spyvm/test/jittest/test_basic.py +++ b/spyvm/test/jittest/test_basic.py @@ -368,6 +368,123 @@ jump(p0, p3, p8, i557, p538, i562, p18, i545, p38, p40, p42, p44, p46, p48, p50, p52, p54, p56, p58, p60, p62, p64, p66, p68, p70, p72, p74, p76, p78, p80, p82, p84, p86, p88, p90, p92, p94, p96, p98, p100, p102, p104, p106, p108, p110, p112, p114, p116, p118, p120, p122, p124, p126, p128, p130, p132, p134, 1, p148, p717, i158, p156, p718, i165, p163, p146, i715, i179, p178, p719, i197, p188, p213, i221, p220, p228, p140, p242, i250, i252, i282, i293, i328, i315, i349, i510, p509, p538, p521, descr=TargetToken(169555520))] """) + # TODO: there shouldnt be allocations in this + def test_range_asOrderedCollection(self, spy, tmpdir): + traces = self.run(spy, tmpdir, + """ + (1 to: 10000) asOrderedCollection. + """) + self.assert_matches(traces[0].loop, """ + guard_not_invalidated(descr=<Guard0x2b713d0>), + p173 = getarrayitem_gc(p53, 1, descr=<ArrayP 4>), + i174 = getfield_gc_pure(p173, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + i175 = int_ge(i174, i167), + guard_true(i175, descr=<Guard0x2b81490>), + cond_call(i75, 4712800, p67, descr=<Callv 0 r EF=2 OS=121>), + cond_call(i103, 4712800, p91, descr=<Callv 0 r EF=2 OS=121>), + cond_call(i103, 4712800, p91, descr=<Callv 0 r EF=2 OS=121>), + p176 = getarrayitem_gc(p105, 0, descr=<ArrayP 4>), + cond_call(i103, 4712800, p91, descr=<Callv 0 r EF=2 OS=121>), + p178 = new_with_vtable(ConstClass(W_SmallInteger)), + setfield_gc(p178, i167, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + setarrayitem_gc(p105, 1, p178, descr=<ArrayP 4>), + setarrayitem_gc(p79, 0, p176, descr=<ArrayP 4>), + setfield_gc(p67, 2, descr=<FieldU spyvm.shadow.ContextPartShadow.inst__stack_ptr 32>), + setfield_gc(p67, 15, descr=<FieldS spyvm.shadow.ContextPartShadow.inst__pc 24>), + setfield_gc(p67, p0, descr=<FieldP spyvm.shadow.ContextPartShadow.inst__s_sender 28>), + setfield_gc(ConstPtr(ptr81), i88, descr=<FieldS spyvm.interpreter.Interpreter.inst_remaining_stack_depth 40>), + setarrayitem_gc(p79, 1, p178, descr=<ArrayP 4>), + guard_class(p176, 6040288, descr=<Guard0x2b81410>), + p179 = getfield_gc(p176, descr=<FieldP spyvm.model.W_AbstractObjectWithClassReference.inst_s_class 12>), + guard_value(p179, ConstPtr(ptr117), descr=<Guard0x2b81390>), + p180 = getfield_gc(p176, descr=<FieldP spyvm.model.W_AbstractPointersObject.inst__shadow 20>), + setarrayitem_gc(p79, 0, ConstPtr(null), descr=<ArrayP 4>), + setfield_gc(p67, 0, descr=<FieldU spyvm.shadow.ContextPartShadow.inst__stack_ptr 32>), + setfield_gc(ConstPtr(ptr81), i129, descr=<FieldS spyvm.interpreter.Interpreter.inst_remaining_stack_depth 40>), + setarrayitem_gc(p79, 1, ConstPtr(null), descr=<ArrayP 4>), + guard_isnull(p180, descr=<Guard0x2b81310>), + p183 = getfield_gc(p176, descr=<FieldP spyvm.model.W_PointersObject.inst_fieldtypes 28>), + guard_value(p183, ConstPtr(ptr133), descr=<Guard0x2b81290>), + p184 = getfield_gc(p176, descr=<FieldP spyvm.model.W_PointersObject.inst__vars 24>), + p185 = getarrayitem_gc(p184, 2, descr=<ArrayP 4>), + p186 = getarrayitem_gc(p184, 0, descr=<ArrayP 4>), + guard_class(p186, 6040288, descr=<Guard0x2b81210>), + p187 = getfield_gc(p186, descr=<FieldP spyvm.model.W_AbstractObjectWithClassReference.inst_s_class 12>), + guard_value(p187, ConstPtr(ptr144), descr=<Guard0x2b81190>), + p188 = getfield_gc(p186, descr=<FieldP spyvm.model.W_AbstractPointersObject.inst__shadow 20>), + guard_isnull(p188, descr=<Guard0x2b81110>), + p189 = getfield_gc(p186, descr=<FieldP spyvm.model.W_PointersObject.inst__vars 24>), + i190 = arraylen_gc(p189, descr=<ArrayP 4>), + i191 = getfield_gc_pure(p185, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + i192 = int_eq(i191, i190), + guard_false(i192, descr=<Guard0x2b81090>), + i193 = int_add_ovf(i191, 1), + guard_no_overflow(descr=<Guard0x2b81010>), + i194 = int_ge(i191, 0), + guard_true(i194, descr=<Guard0x2b71f50>), + i195 = int_lt(i191, i190), + guard_true(i195, descr=<Guard0x2b71ed0>), + p196 = getfield_gc(p186, descr=<FieldP spyvm.model.W_PointersObject.inst_fieldtypes 28>), + guard_value(p196, ConstPtr(ptr156), descr=<Guard0x2b71e50>), + p197 = new_with_vtable(ConstClass(W_SmallInteger)), + setfield_gc(p197, i193, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + setarrayitem_gc(p184, 2, p197, descr=<ArrayP 4>), + setarrayitem_gc(p189, i191, p178, descr=<ArrayP 4>), + p198 = getarrayitem_gc(p53, 2, descr=<ArrayP 4>), + i199 = getfield_gc_pure(p198, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + setarrayitem_gc(p79, 0, ConstPtr(null), descr=<ArrayP 4>), + setfield_gc(p67, -1, descr=<FieldS spyvm.shadow.ContextPartShadow.inst__pc 24>), + setfield_gc(p67, ConstPtr(null), descr=<FieldP spyvm.shadow.ContextPartShadow.inst__s_sender 28>), + setfield_gc(ConstPtr(ptr81), i84, descr=<FieldS spyvm.interpreter.Interpreter.inst_remaining_stack_depth 40>), + i200 = int_add_ovf(i167, i199), + guard_no_overflow(descr=<Guard0x2b71dd0>), + i201 = int_sub(i170, 8), + setfield_gc(ConstPtr(ptr81), i201, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 24>), + i202 = int_le(i201, 0), + guard_false(i202, descr=<Guard0x2b71d50>), + i203 = arraylen_gc(p53, descr=<ArrayP 4>), + i204 = arraylen_gc(p79, descr=<ArrayP 4>), + i205 = arraylen_gc(p105, descr=<ArrayP 4>), + jump(p0, p3, p6, i200, p14, p16, p18, p20, p22, p24, p26, p28, p30, p32, p34, p36, p38, p40, p42, p53, i75, p67, i103, p91, p105, p79, i88, i90, i129, i84, i201, descr=TargetToken(45055856))] + """) + + def test_indexOf(self, spy, tmpdir): + traces = self.run(spy, tmpdir, + """ + (1 to: 10000000) asOrderedCollection indexOf: 9999999. + """) + # First loop: asOrderedCollection, second loop: makeRoomAtLast + self.assert_matches(traces[2].loop, """ + guard_not_invalidated(descr=<Guard0x2bac7d0>), + i127 = int_le(i121, i61), + guard_true(i127, descr=<Guard0x2bac790>), + setfield_gc(ConstPtr(ptr74), i81, descr=<FieldS spyvm.interpreter.Interpreter.inst_remaining_stack_depth 40>), + i128 = int_add_ovf(i121, i91), + guard_no_overflow(descr=<Guard0x2bac750>), + i129 = int_sub(i128, 1), + i130 = int_gt(i129, i97), + guard_false(i130, descr=<Guard0x2bac710>), + i131 = int_sub(i129, 1), + i132 = int_ge(i131, 0), + guard_true(i132, descr=<Guard0x2bac6d0>), + i133 = int_lt(i131, i110), + guard_true(i133, descr=<Guard0x2bac690>), + p134 = getarrayitem_gc(p109, i131, descr=<ArrayP 4>), + setfield_gc(ConstPtr(ptr74), i77, descr=<FieldS spyvm.interpreter.Interpreter.inst_remaining_stack_depth 40>), + guard_nonnull_class(p134, ConstClass(W_SmallInteger), descr=<Guard0x2bac650>), + i135 = getfield_gc_pure(p134, descr=<FieldS spyvm.model.W_SmallInteger.inst_value 8>), + i136 = int_eq(i135, i118), + guard_false(i136, descr=<Guard0x2bac610>), + i137 = int_add_ovf(i121, 1), + guard_no_overflow(descr=<Guard0x2bac5d0>), + i138 = int_sub(i124, 6), + setfield_gc(ConstPtr(ptr74), i138, descr=<FieldS spyvm.interpreter.Interpreter.inst_interrupt_check_counter 24>), + i139 = int_le(i138, 0), + guard_false(i139, descr=<Guard0x2bac590>), + i140 = arraylen_gc(p88, descr=<ArrayP 4>), + jump(p0, p3, p6, p8, p10, i137, p14, p20, p22, p24, p26, p28, p30, p32, p34, p36, p38, p40, p42, p44, p46, p48, p50, p52, i61, i81, i91, p63, p90, i67, i97, p96, p100, i110, p109, i77, i118, i138, p88, descr=TargetToken(45201344))] + """) + @py.test.mark.skipif("'just dozens of long traces'") def test_bitblt_draw_windows(self, spy, tmpdir): # This used to have a call to array comparison in it diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py --- a/spyvm/test/test_interpreter.py +++ b/spyvm/test/test_interpreter.py @@ -57,12 +57,12 @@ assert space.get_special_selector(methname) is symbol s_class.installmethod(symbol, prim_meth) - assert space.w_nil._shadow is None + assert space.w_nil.shadow is None try: func(active_context) if active_context else func() finally: # Uninstall those methods: - assert space.w_nil._shadow is None + assert space.w_nil.shadow is None for (w_class, _, _, methname) in methods: s_class = w_class.as_class_get_shadow(space) s_class.update() diff --git a/spyvm/test/test_largeinteger.py b/spyvm/test/test_largeinteger.py --- a/spyvm/test/test_largeinteger.py +++ b/spyvm/test/test_largeinteger.py @@ -30,8 +30,7 @@ initialize_class(w("string").getclass(tools.space)) def perform_primitive(rcvr, w_selector, *args): - - code = rcvr.getclass(space)._shadow.lookup(w_selector).primitive() + code = rcvr.getclass(space).shadow.lookup(w_selector).primitive() assert code func = primitives.prim_holder.prim_table[code] s_frame = MockFrame([rcvr] + list(args)).as_context_get_shadow(space) @@ -52,7 +51,7 @@ try: w_selector = space.get_special_selector(selector) except Exception: - w_selector = find_symbol_in_methoddict_of(selector, w(intmask(candidates[0])).getclass(space)._shadow) + w_selector = find_symbol_in_methoddict_of(selector, w(intmask(candidates[0])).getclass(space).shadow) interp.trace=trace for i, v in enumerate(candidates): diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py --- a/spyvm/test/test_miniimage.py +++ b/spyvm/test/test_miniimage.py @@ -407,7 +407,7 @@ w_o = space.wrap_list([1, 2, 3]) w_methoddict = w_o.shadow_of_my_class(space)._s_superclass._s_superclass.w_methoddict() w_methoddict.as_methoddict_get_shadow(space).sync_cache() - selectors_w = w_methoddict._shadow.methoddict.keys() + selectors_w = w_methoddict.shadow.methoddict.keys() w_sel = None for sel in selectors_w: if sel.as_string() == 'size': diff --git a/spyvm/test/test_objectspace.py b/spyvm/test/test_objectspace.py --- a/spyvm/test/test_objectspace.py +++ b/spyvm/test/test_objectspace.py @@ -8,7 +8,7 @@ # Heuristic to detect if this is a metaclass. Don't use apart # from in this test file, because classtable['w_Metaclass'] is # bogus after loading an image. - return w_cls.s_class is space.classtable['w_Metaclass']._shadow + return w_cls.s_class is space.classtable['w_Metaclass'].shadow def test_every_class_is_an_instance_of_a_metaclass(): for (nm, w_cls) in space.classtable.items(): 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 @@ -23,8 +23,8 @@ self.s_class = space.w_MethodContext.as_class_get_shadow(space) def as_blockcontext_get_shadow(self): - self._shadow = shadow.BlockContextShadow(space, self) - return self._shadow + self.shadow = shadow.BlockContextShadow(space, self) + return self.shadow def wrap(x): if isinstance(x, int): return space.wrap_int(x) @@ -806,13 +806,13 @@ interp.image = Image() try: - monkeypatch.setattr(w_frame._shadow, "_sendSelfSelector", perform_mock) + monkeypatch.setattr(w_frame.shadow, "_sendSelfSelector", perform_mock) monkeypatch.setattr(bitblt.BitBltShadow, "sync_cache", 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: monkeypatch.undo() - assert w_frame._shadow.pop() is mock_bitblt # the receiver + assert w_frame.shadow.pop() is mock_bitblt # the receiver # Note: # primitives.NEXT is unimplemented as it is a performance optimization diff --git a/spyvm/test/test_shadow.py b/spyvm/test/test_shadow.py --- a/spyvm/test/test_shadow.py +++ b/spyvm/test/test_shadow.py @@ -171,11 +171,11 @@ w_object = blockcontext(pc=13) old_vars = w_object._vars s_object = w_object.as_blockcontext_get_shadow(space) - s_object._shadow = None + s_object.shadow = None s_newobject = w_object.as_blockcontext_get_shadow(space) assert ([s_newobject.fetch(i) for i in range(s_newobject.size())] == [s_object.fetch(i) for i in range(s_newobject.size())]) - assert w_object._shadow is s_newobject + assert w_object.shadow is s_newobject def test_compiledmethodshadow(): from test_model import joinbits @@ -222,7 +222,7 @@ assert o.notified assert w_o.fetch(space, 0) == 1 try: - w_o._shadow.notify(Observer()) + w_o.shadow.notify(Observer()) except RuntimeError: pass else: diff --git a/spyvm/version.py b/spyvm/version.py new file mode 100644 --- /dev/null +++ b/spyvm/version.py @@ -0,0 +1,40 @@ +from rpython.rlib import jit + +# This declares the decorated function as "pure" while the self-object +# has an unchanged version. Neither self nor self.version are promoted to constants. +def elidable_for_version(func): + @jit.elidable + def elidable_func(self, version, *args): + return func(self, *args) + def meth(self, *args): + return elidable_func(self, self.version, *args) + elidable_func.func_name = "elidable_" + func.func_name + meth.func_name = "elidable_meth_" + func.func_name + return meth + +# In addition to marking the decorated function as "pure", both the receiver +# and the version of the receiver are promoted to constants. This should only +# be used in situations where the receiver is very unlikely to change in the same +# context of the interpreted program (like classes or compiled methods). +def constant_for_version(func): + @jit.elidable + def elidable_func(self, version, *args): + return func(self, *args) + def meth(self, *args): + self = jit.promote(self) + version = jit.promote(self.version) + return elidable_func(self, version, *args) + return meth + +class Version(object): + pass + +class VersionMixin(object): + # Concrete class must define a pseudo immutable field like the following: + # _attrs_ = ['version'] + # _immutable_fields_ = ['version?'] + + version = Version() + + def changed(self): + self.version = Version() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit