[pypy-commit] lang-smalltalk storage: To determine the containing class of a CompiledMethod, use the class it has been looked up in.

anton_gulenko noreply at buildbot.pypy.org
Mon Apr 7 13:52:31 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage
Changeset: r776:fc5bb4c06b5f
Date: 2014-04-04 17:24 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/fc5bb4c06b5f/

Log:	To determine the containing class of a CompiledMethod, use the class
	it has been looked up in. This reduces dependence on literals being
	stored in a certain way we expect them to be.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -1226,6 +1226,11 @@
         self.bytes[index0] = character
         self.changed()
     
+    def set_compiled_in(self, w_compiledin):
+        if not self.w_compiledin:
+            self.w_compiledin = w_compiledin
+            self.changed()
+    
     # === Getters ===
         
     def getclass(self, space):
@@ -1277,23 +1282,31 @@
     def compiled_in(self):
         w_compiledin = self.w_compiledin
         if not w_compiledin:
-            literals = self.literals
-            if literals and len(literals) > 0:
-                # (Blue book, p 607) Last of the literals is either the containing class 
-                # or an association with compiledin as a class
-                w_candidate = literals[-1]
-                if isinstance(w_candidate, W_PointersObject) and w_candidate.has_space():
-                    space = w_candidate.space() # Not pretty to steal the space from another object.
+            # If the method has not been looked up from a methoddict yet, try to get the
+            # containing class from it's literals. This should be rare in practice.
+            w_compiledin = self.compiled_in_from_literals()
+            self.w_compiledin = w_compiledin
+        assert w_compiledin is None or isinstance(w_compiledin, W_PointersObject)
+        return w_compiledin
+    
+    @jit.dont_look_inside # Tracing into this function is useless.
+    def compiled_in_from_literals(self):
+        w_compiledin = None
+        literals = self.literals
+        if literals and len(literals) > 0:
+            # (Blue book, p 607) Last of the literals is either the containing class 
+            # or an association with compiledin as a class
+            w_candidate = literals[-1]
+            if isinstance(w_candidate, W_PointersObject) and w_candidate.has_space():
+                space = w_candidate.space() # Not pretty to steal the space from another object.
+                if w_candidate.is_class(space):
+                    w_compiledin = w_candidate
+                elif w_candidate.size() >= 2:
+                    from spyvm import wrapper
+                    association = wrapper.AssociationWrapper(space, w_candidate)
+                    w_candidate = association.value()
                     if w_candidate.is_class(space):
                         w_compiledin = w_candidate
-                    elif w_candidate.size() >= 2:
-                        from spyvm import wrapper
-                        association = wrapper.AssociationWrapper(space, w_candidate)
-                        w_candidate = association.value()
-                        if w_candidate.is_class(space):
-                            w_compiledin = w_candidate
-            self.w_compiledin = w_compiledin
-        assert w_compiledin is None or isinstance(w_compiledin, W_PointersObject)
         return w_compiledin
     
     # === Object Access ===
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -480,10 +480,7 @@
         while look_in_shadow is not None:
             w_method = look_in_shadow.s_methoddict().find_selector(w_selector)
             if w_method is not None:
-                # Old images don't store compiledin-info in literals.
-                if not w_method.w_compiledin:
-                    w_method.w_compiledin = look_in_shadow.w_self()
-                    w_method.changed()
+                w_method.set_compiled_in(look_in_shadow.w_self())
                 return w_method
             look_in_shadow = look_in_shadow._s_superclass
         raise MethodNotFound(self, w_selector)
diff --git a/spyvm/test/test_model.py b/spyvm/test/test_model.py
--- a/spyvm/test/test_model.py
+++ b/spyvm/test/test_model.py
@@ -93,6 +93,8 @@
     class mockmethod(object):
         def __init__(self, val):
             self.val = val
+        def set_compiled_in(self, w):
+            pass
     w_class = bootstrap_class(0)
     shadow = w_class.as_class_get_shadow(space)
     shadow.installmethod(w_foo, mockmethod(1))


More information about the pypy-commit mailing list