Author: Anton Gulenko <[email protected]>
Branch: storage-context-state-v2
Changeset: r959:b76819c9b3b6
Date: 2014-07-27 11:18 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/b76819c9b3b6/
Log: Removed LocalReturn exception, handling it with flags in the Return
exception. This fixed drawing issue in the mini image.
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -11,11 +11,13 @@
self.object = object
class Return(Exception):
- _attrs_ = ["value", "s_target_context", "is_local"]
- def __init__(self, s_target_context, w_result, is_local):
+ _attrs_ = ["value", "s_target_context", "is_local", "arrived_at_target"]
+ _immutable_attrs_ = ["value", "s_target_context", "is_local"]
+ def __init__(self, s_target_context, w_result):
self.value = w_result
self.s_target_context = s_target_context
- self.is_local = is_local
+ self.arrived_at_target = False
+ self.is_local = s_target_context is None
class NonVirtualReturn(Exception):
_attrs_ = ["s_target_context", "s_current_context", "value"]
@@ -27,11 +29,6 @@
def print_trace(self):
print "\n====== Sender Chain Manipulation, contexts forced to heap at:
%s" % self.s_current_context.short_str()
-class LocalReturn(Exception):
- _attrs_ = ["value"]
- def __init__(self, value):
- self.value = value
-
class ContextSwitchException(Exception):
"""General Exception that causes the interpreter to leave
the current context."""
@@ -108,14 +105,13 @@
if self.is_tracing():
e.print_trace()
s_context = e.s_new_context
- except LocalReturn, ret:
- s_context = self.unwind_context_chain(s_sender, s_sender,
ret.value, "LocalReturn")
except Return, ret:
- s_context = self.unwind_context_chain(s_sender,
ret.s_target_context, ret.value, "Return")
+ target = s_sender if ret.arrived_at_target else
ret.s_target_context
+ s_context = self.unwind_context_chain(s_sender, target,
ret.value)
except NonVirtualReturn, ret:
if self.is_tracing():
ret.print_trace()
- s_context = self.unwind_context_chain(ret.s_current_context,
ret.s_target_context, ret.value, "NonVirtual")
+ s_context = self.unwind_context_chain(ret.s_current_context,
ret.s_target_context, ret.value)
# This is a wrapper around loop_bytecodes that cleanly enters/leaves the
frame,
# handles the stack overflow protection mechanism and handles/dispatches
Returns.
@@ -140,10 +136,9 @@
raise NonVirtualReturn(target_context, s_sender, ret.value)
else:
s_frame._activate_unwind_context(self)
- if ret.s_target_context is s_sender or ret.is_local:
- raise LocalReturn(ret.value)
- else:
- raise ret
+ if ret.is_local or ret.s_target_context is s_sender:
+ ret.arrived_at_target = True
+ raise ret
finally:
if self.is_tracing():
self.stack_depth -= 1
@@ -169,10 +164,13 @@
s_context=s_context)
try:
self.step(s_context)
- except LocalReturn, ret:
- s_context.push(ret.value)
+ except Return, ret:
+ if ret.arrived_at_target:
+ s_context.push(ret.value)
+ else:
+ raise ret
- def unwind_context_chain(self, start_context, target_context,
return_value, source=""):
+ def unwind_context_chain(self, start_context, target_context,
return_value):
if start_context is None:
# This is the toplevel frame. Execution ended.
raise ReturnFromTopLevel(return_value)
@@ -180,8 +178,7 @@
context = start_context
while context is not target_context:
if not context:
- msg = "Context chain ended (source: %s) while trying to
return\n%s\nfrom\n%s\n(pc %s)\nto\n%s\n(pc %s)" % (
- source,
+ msg = "Context chain ended while trying to
return\n%s\nfrom\n%s\n(pc %s)\nto\n%s\n(pc %s)" % (
return_value.as_repr_string(),
start_context.short_str(),
start_context.pc(),
diff --git a/spyvm/interpreter_bytecodes.py b/spyvm/interpreter_bytecodes.py
--- a/spyvm/interpreter_bytecodes.py
+++ b/spyvm/interpreter_bytecodes.py
@@ -393,13 +393,12 @@
# it will find the sender as a local, and we don't have to
# force the reference
s_return_to = None
- is_local = True
else:
s_return_to = self.s_home().s_sender()
- is_local = False
+ assert s_return_to, "No sender to return to!"
from spyvm.interpreter import Return
- raise Return(s_return_to, return_value, is_local)
+ raise Return(s_return_to, return_value)
# ====== Send/Return bytecodes ======
@@ -494,12 +493,13 @@
if self.gettemp(1).is_nil(self.space):
self.settemp(1, self.space.w_true) # mark unwound
self.push(self.gettemp(0)) # push the first argument
- from spyvm.interpreter import LocalReturn
+ from spyvm.interpreter import Return
try:
self.bytecodePrimValue(interp, 0)
- except LocalReturn:
+ except Return, ret:
# Local return value of ensure: block is ignored
- pass
+ if not ret.arrived_at_target:
+ raise ret
finally:
self.mark_returned()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit