[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