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

Reply via email to