[pypy-commit] lang-smalltalk default: moved the returning-context identification from the copy of returnTopFromMethod to s_home, because simply overwriting returnTopFromMethod in MethodContextShadow is not sufficient for implementing Non-local-return. E.g. ReturnNil also needs that changed behavior.

lwassermann noreply at buildbot.pypy.org
Tue May 28 18:27:18 CEST 2013


Author: Lars Wassermann <lars.wassermann at gmail.com>
Branch: 
Changeset: r418:0c6b78a77dca
Date: 2013-05-28 18:24 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/0c6b78a77dca/

Log:	moved the returning-context identification from the copy of
	returnTopFromMethod to s_home, because simply overwriting
	returnTopFromMethod in MethodContextShadow is not sufficient for
	implementing Non-local-return. E.g. ReturnNil also needs that
	changed behavior.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -447,7 +447,6 @@
         return self._return(interp.space.w_nil, interp, self.s_home().s_sender())
 
     def returnTopFromMethod(self, interp, current_bytecode):
-        # overwritten in MethodContextShadow
         return self._return(self.pop(), interp, self.s_home().s_sender())
 
     def returnTopFromBlock(self, interp, current_bytecode):
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -947,7 +947,18 @@
         return self.w_self()
 
     def s_home(self):
-        return self
+        if self.is_closure_context():
+            # this is a context for a blockClosure
+            w_outerContext = self.w_closure_or_nil.fetch(self.space,
+                constants.BLKCLSR_OUTER_CONTEXT)
+            assert isinstance(w_outerContext, model.W_PointersObject)
+            s_outerContext = w_outerContext.as_context_get_shadow(self.space)
+            # XXX check whether we can actually return from that context
+            if s_outerContext.pc() == -1:
+                raise error.BlockCannotReturnError()
+            return s_outerContext.s_home()
+        else:
+            return self
 
     def stackpointer_offset(self):
         return constants.MTHDCTX_TEMP_FRAME_START
@@ -958,21 +969,6 @@
     def myblocksize(self):
         return self.size() - self.tempsize()
 
-    def returnTopFromMethod(self, interp, current_bytecode):
-        if self.is_closure_context():
-            # this is a context for a blockClosure
-            w_outerContext = self.w_closure_or_nil.fetch(self.space,
-                constants.BLKCLSR_OUTER_CONTEXT)
-            assert isinstance(w_outerContext, model.W_PointersObject)
-            s_outerContext = w_outerContext.as_context_get_shadow(self.space)
-            # XXX check whether we can actually return from that context
-            if s_outerContext.pc() == -1:
-                raise error.BlockCannotReturnError()
-            return_to_context = s_outerContext.s_home().s_sender()
-        else:
-            return_to_context = self.s_home().s_sender()
-        return self._return(self.pop(), interp, return_to_context)
-
     def is_closure_context(self):
         return self.w_closure_or_nil is not self.space.w_nil
 
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
@@ -282,3 +282,14 @@
     assert w_context.fetch(space, constants.CTXPART_PC_INDEX) is not space.w_nil
     s_context.mark_returned()
     assert w_context.fetch(space, constants.CTXPART_PC_INDEX) is space.w_nil
+
+def test_methodcontext_s_home():
+    from spyvm.wrapper import BlockClosureWrapper
+    w_context = methodcontext()
+    s_context = w_context.as_methodcontext_get_shadow(space)
+    w_middle_context = methodcontext(w_sender=w_context)
+    s_middle_context = w_middle_context.as_methodcontext_get_shadow(space)
+
+    w_closure = space.newClosure(w_context, 3, 0, [])
+    s_closure_context = BlockClosureWrapper(space, w_closure).asContextWithSender(w_middle_context, [])
+    assert s_closure_context.s_home() is s_context


More information about the pypy-commit mailing list