Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: Changeset: r167:500374918ff4 Date: 2013-03-12 18:43 +0100 http://bitbucket.org/pypy/lang-smalltalk/changeset/500374918ff4/
Log: make more attributes on shadows immutable per version. invent a decorator to automate this. diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py --- a/spyvm/interpreter.py +++ b/spyvm/interpreter.py @@ -290,9 +290,9 @@ s_method = receiverclassshadow.lookup(w_selector) # XXX catch MethodNotFound here and send doesNotUnderstand: # AK shouln't that be done in lookup itself, please check what spec says about DNU in case of super sends. - if s_method.primitive: + code = s_method.primitive() + if code: # the primitive pushes the result (if any) onto the stack itself - code = s_method.primitive if interp.should_trace(): print "%sActually calling primitive %d" % (interp._last_indent, code,) func = primitives.prim_holder.prim_table[code] diff --git a/spyvm/objspace.py b/spyvm/objspace.py --- a/spyvm/objspace.py +++ b/spyvm/objspace.py @@ -299,7 +299,7 @@ s._s_superclass = None s.store_w_superclass(w_superclass) s.name = name - s.instance_size = instsize + s._instance_size = instsize s.instance_kind = format s._s_methoddict = None s.instance_varsized = varsized or format != shadow.POINTERS diff --git a/spyvm/shadow.py b/spyvm/shadow.py --- a/spyvm/shadow.py +++ b/spyvm/shadow.py @@ -3,6 +3,16 @@ 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 + class AbstractShadow(object): """A shadow is an optional extra bit of information that can be attached at run-time to any Smalltalk object. @@ -74,7 +84,7 @@ (i.e. used as the class of another Smalltalk object). """ - _attr_ = ["name", "instance_size", "instance_varsized", "instance_kind", + _attr_ = ["name", "_instance_size", "instance_varsized", "instance_kind", "_s_methoddict", "_s_superclass", "subclass_s"] def __init__(self, space, w_self): @@ -109,7 +119,7 @@ # compute the instance size (really the size, not the number of bytes) instsize_lo = (classformat >> 1) & 0x3F instsize_hi = (classformat >> (9 + 1)) & 0xC0 - self.instance_size = (instsize_lo | instsize_hi) - 1 # subtract hdr + self._instance_size = (instsize_lo | instsize_hi) - 1 # subtract hdr # decode the instSpec format = (classformat >> 7) & 15 self.instance_varsized = format >= 2 @@ -119,12 +129,12 @@ self.instance_kind = WEAK_POINTERS elif format == 6: self.instance_kind = WORDS - if self.instance_size != 0: + if self.instsize() != 0: raise ClassShadowError("can't have both words and a non-zero " "base instance size") elif 8 <= format <= 11: self.instance_kind = BYTES - if self.instance_size != 0: + if self.instsize() != 0: raise ClassShadowError("can't have both bytes and a non-zero " "base instance size") elif 12 <= format <= 15: @@ -184,7 +194,7 @@ def new(self, extrasize=0): w_cls = self.w_self() if self.instance_kind == POINTERS: - w_new = model.W_PointersObject(w_cls, self.instance_size+extrasize) + w_new = model.W_PointersObject(w_cls, self.instsize()+extrasize) elif self.instance_kind == WORDS: w_new = model.W_WordsObject(w_cls, extrasize) elif self.instance_kind == BYTES: @@ -226,13 +236,15 @@ " True if instances of this class have data stored as numerical bytes " return self.format == BYTES + @make_elidable_after_versioning def isvariable(self): " True if instances of this class have indexed inst variables " return self.instance_varsized + @make_elidable_after_versioning def instsize(self): " Number of named instance variables for each instance of this class " - return self.instance_size + return self._instance_size def store_w_superclass(self, w_class): if w_class is None: @@ -269,17 +281,9 @@ def __repr__(self): return "<ClassShadow %s>" % (self.name or '?',) + @make_elidable_after_versioning def lookup(self, w_selector): - jit.promote(self) - version = self.version - jit.promote(version) - return self.safe_lookup(w_selector, version) - - @jit.elidable - def safe_lookup(self, w_selector, version): - assert version is self.version look_in_shadow = self - jit.promote(w_selector) while look_in_shadow is not None: s_method = look_in_shadow.s_methoddict().find_selector(w_selector) if s_method is not None: @@ -573,7 +577,7 @@ def getbytecode(self): jit.promote(self._pc) assert self._pc >= 0 - bytecode = self.s_method().bytecode[self._pc] + bytecode = self.s_method().getbytecode(self._pc) currentBytecode = ord(bytecode) self._pc += 1 return currentBytecode @@ -667,7 +671,7 @@ if self._w_self is not None: return self._w_self else: - size = self.size() - self.space.w_MethodContext.as_class_get_shadow(self.space).instance_size + size = self.size() - self.space.w_MethodContext.as_class_get_shadow(self.space).instsize() space = self.space w_self = space.w_MethodContext.as_class_get_shadow(space).new(size) w_self.store_shadow(self) @@ -799,7 +803,7 @@ # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 size = (12 + s_method.islarge * 20 + s_method.argsize - + space.w_MethodContext.as_class_get_shadow(space).instance_size) + + space.w_MethodContext.as_class_get_shadow(space).instsize()) # The last summand is needed, because we calculate i.a. our stackdepth relative of the size of w_self. s_new_context = MethodContextShadow(space, None) @@ -862,7 +866,7 @@ def tempsize(self): if not self.is_closure_context(): - return self.s_method().tempsize + return self.s_method().tempsize() else: return wrapper.BlockClosureWrapper(self.space, self.w_closure_or_nil).tempsize() @@ -948,15 +952,8 @@ def w_self(self): return self._w_self + @make_elidable_after_versioning def getliteral(self, index): - jit.promote(self) - version = self.version - jit.promote(version) - return self.safe_getliteral(index, version) - - @jit.elidable - def safe_getliteral(self, index, version): - assert version is self.version return self.literals[index] def getliteralsymbol(self, index): @@ -971,8 +968,8 @@ self.literals = w_compiledmethod.literals self.bytecodeoffset = w_compiledmethod.bytecodeoffset() self.literalsize = w_compiledmethod.getliteralsize() - self.tempsize = w_compiledmethod.gettempsize() - self.primitive = w_compiledmethod.primitive + self._tempsize = w_compiledmethod.gettempsize() + self._primitive = w_compiledmethod.primitive self.argsize = w_compiledmethod.argsize self.islarge = w_compiledmethod.islarge @@ -989,12 +986,24 @@ association = wrapper.AssociationWrapper(None, w_association) self.w_compiledin = association.value() + @make_elidable_after_versioning + def tempsize(self): + return self._tempsize + + @make_elidable_after_versioning + def primitive(self): + return self._primitive + def create_frame(self, space, receiver, arguments, sender = None): assert len(arguments) == self.argsize s_new = MethodContextShadow.make_context( space, self, receiver, arguments, sender) return s_new + @make_elidable_after_versioning + def getbytecode(self, pc): + return self.bytecode[pc] + class CachedObjectShadow(AbstractCachingShadow): def fetch(self, n0): 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 @@ -186,7 +186,7 @@ assert shadow.bytecode == "abc" assert shadow.bytecodeoffset == 12 assert shadow.literalsize == 8 # 12 - 4byte header - assert shadow.tempsize == 1 + assert shadow.tempsize() == 1 w_compiledmethod.literalatput0(space, 1, 17) w_compiledmethod.literalatput0(space, 2, 41) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit