[pypy-commit] lang-smalltalk storage-context-state-v2: Added the rest of the refactoring.
anton_gulenko
noreply at buildbot.pypy.org
Sun Jul 27 12:22:18 CEST 2014
Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage-context-state-v2
Changeset: r955:92d182dabea1
Date: 2014-07-25 16:33 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/92d182dabea1/
Log: Added the rest of the refactoring.
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -1,7 +1,7 @@
import os
from spyvm.shadow import MethodContextShadow, ActiveContext, InactiveContext, DirtyContext
-from spyvm import model, constants, wrapper, objspace, interpreter_bytecodes
+from spyvm import model, constants, wrapper, objspace, interpreter_bytecodes, error
from rpython.rlib import jit, rstackovf, unroll
@@ -17,6 +17,16 @@
self.s_target_context = s_target_context
self.is_local = is_local
+class NonVirtualReturn(Exception):
+ _attrs_ = ["s_target_context", "s_current_context", "value"]
+ def __init__(self, s_target_context, s_current_context, w_result):
+ self.value = w_result
+ self.s_target_context = s_target_context
+ self.s_current_context = s_current_context
+
+ 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):
@@ -25,14 +35,13 @@
class ContextSwitchException(Exception):
"""General Exception that causes the interpreter to leave
the current context."""
-
_attrs_ = ["s_new_context"]
type = "ContextSwitch"
def __init__(self, s_new_context):
self.s_new_context = s_new_context
- def print_trace(self, old_context):
- print "====== %s, contexts forced to heap at: %s" % (self.type, self.s_new_context.short_str())
+ def print_trace(self):
+ print "\n====== %s at: %s" % (self.type, self.s_new_context.short_str())
class StackOverflow(ContextSwitchException):
"""This causes the current jit-loop to be left, dumping all virtualized objects to the heap.
@@ -43,17 +52,8 @@
class ProcessSwitch(ContextSwitchException):
"""This causes the interpreter to switch the executed context.
Triggered when switching the process."""
+ type = "Process Switch"
- def print_trace(self, old_context):
- print "====== Switched process from: %s" % old_context.short_str()
- print "====== to: %s " % self.s_new_context.short_str()
-
-class SenderChainManipulation(ContextSwitchException):
- """Manipulation of the sender chain can invalidate the jitted C stack.
- We have to dump all virtual objects and rebuild the stack.
- We try to raise this as rarely as possible and as late as possible."""
- type = "Sender Manipulation"
-
UNROLLING_BYTECODE_RANGES = unroll.unrolling_iterable(interpreter_bytecodes.BYTECODE_RANGES)
def get_printable_location(pc, self, method):
@@ -98,23 +98,27 @@
def loop(self, w_active_context):
# This is the top-level loop and is not invoked recursively.
- s_new_context = w_active_context.as_context_get_shadow(self.space)
+ s_context = w_active_context.as_context_get_shadow(self.space)
while True:
- s_sender = s_new_context.s_sender()
+ s_sender = s_context.s_sender()
try:
- self.stack_frame(s_new_context, None)
+ self.stack_frame(s_context, None)
raise Exception("loop_bytecodes left without raising...")
except ContextSwitchException, e:
if self.is_tracing():
- e.print_trace(s_new_context)
- s_new_context = e.s_new_context
+ e.print_trace()
+ s_context = e.s_new_context
except LocalReturn, ret:
- s_new_context = self.unwind_context_chain(s_sender, s_sender, ret.value)
+ s_context = self.unwind_context_chain(s_sender, s_sender, ret.value, "LocalReturn")
except Return, ret:
- s_new_context = self.unwind_context_chain(s_sender, ret.s_target_context, ret.value)
+ s_context = self.unwind_context_chain(s_sender, ret.s_target_context, ret.value, "Return")
+ 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")
- # This is a wrapper around loop_bytecodes that cleanly enters/leaves the frame
- # and handles the stack overflow protection mechanism.
+ # This is a wrapper around loop_bytecodes that cleanly enters/leaves the frame,
+ # handles the stack overflow protection mechanism and handles/dispatches Returns.
def stack_frame(self, s_frame, s_sender, may_context_switch=True):
try:
if self.is_tracing():
@@ -129,17 +133,21 @@
rstackovf.check_stack_overflow()
raise StackOverflow(s_frame)
except Return, ret:
- if ret.is_local:
- raise LocalReturn(ret.value)
+ if s_frame.state is DirtyContext:
+ s_sender = s_frame.s_sender() # The sender has changed!
+ s_frame._activate_unwind_context(self)
+ target_context = s_sender if ret.is_local else ret.s_target_context
+ raise NonVirtualReturn(target_context, s_sender, ret.value)
else:
- raise ret
+ 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
finally:
if self.is_tracing():
self.stack_depth -= 1
- dirty_frame = s_frame.state is DirtyContext
s_frame.state = InactiveContext
- if dirty_frame:
- raise SenderChainManipulation(s_frame)
def loop_bytecodes(self, s_context, may_context_switch=True):
old_pc = 0
@@ -164,14 +172,22 @@
except LocalReturn, ret:
s_context.push(ret.value)
- def unwind_context_chain(self, start_context, target_context, return_value):
+ def unwind_context_chain(self, start_context, target_context, return_value, source=""):
if start_context is None:
# This is the toplevel frame. Execution ended.
raise ReturnFromTopLevel(return_value)
assert target_context
context = start_context
while context is not target_context:
- assert context, "Sender chain ended without finding return-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,
+ return_value.as_repr_string(),
+ start_context.short_str(),
+ start_context.pc(),
+ target_context.short_str(),
+ start_context.pc())
+ raise error.FatalError(msg)
s_sender = context.s_sender()
context._activate_unwind_context(self)
context = s_sender
diff --git a/spyvm/interpreter_bytecodes.py b/spyvm/interpreter_bytecodes.py
--- a/spyvm/interpreter_bytecodes.py
+++ b/spyvm/interpreter_bytecodes.py
@@ -30,7 +30,8 @@
parameters += (self.fetch_next_bytecode(), )
i = i + 1
# This is a good place to step through bytecodes.
- self.debug_bytecode()
+
+ self.debug_bytecode(interp)
return actual_implementation_method(self, interp, current_bytecode, *parameters)
bytecode_implementation_wrapper.func_name = actual_implementation_method.func_name
return bytecode_implementation_wrapper
@@ -118,7 +119,7 @@
def pushLiteralVariableBytecode(self, interp, current_bytecode):
# this bytecode assumes that literals[index] is an Association
# which is an object with two named vars, and fetches the second
- # named var (the value).
+ # named var (the value).
index = current_bytecode & 31
w_association = self.w_method().getliteral(index)
association = wrapper.AssociationWrapper(self.space, w_association)
@@ -337,8 +338,6 @@
# ######################################################################
if interp.is_tracing():
interp.print_padded('-> %s %s' % (special_selector, s_frame.short_str()))
- if not objectmodel.we_are_translated():
- import pdb; pdb.set_trace()
return interp.stack_frame(s_frame, self)
@@ -445,7 +444,6 @@
@bytecode_implementation(parameter_bytes=2)
def doubleExtendedDoAnythingBytecode(self, interp, current_bytecode, second, third):
- from spyvm.interpreter import SenderChainManipulation
opType = second >> 5
if opType == 0:
# selfsend
@@ -467,16 +465,9 @@
association = wrapper.AssociationWrapper(self.space, w_association)
self.push(association.value())
elif opType == 5:
- # TODO - the following two special cases should not be necessary
- try:
- self.w_receiver().store(self.space, third, self.top())
- except SenderChainManipulation, e:
- raise SenderChainManipulation(self)
+ self.w_receiver().store(self.space, third, self.top())
elif opType == 6:
- try:
- self.w_receiver().store(self.space, third, self.pop())
- except SenderChainManipulation, e:
- raise SenderChainManipulation(self)
+ self.w_receiver().store(self.space, third, self.pop())
elif opType == 7:
w_association = self.w_method().getliteral(third)
association = wrapper.AssociationWrapper(self.space, w_association)
@@ -607,7 +598,7 @@
bytecodePrimPointX = make_send_selector_bytecode("x", 0)
bytecodePrimPointY = make_send_selector_bytecode("y", 0)
- def debug_bytecode(self):
+ def debug_bytecode(self, interp):
# Hook used in interpreter_debugging
pass
diff --git a/spyvm/interpreter_debugging.py b/spyvm/interpreter_debugging.py
--- a/spyvm/interpreter_debugging.py
+++ b/spyvm/interpreter_debugging.py
@@ -49,8 +49,8 @@
@patch_context
def debug_bytecode(original):
- def meth(self):
- if self.step_bytecodes:
+ def meth(self, interp):
+ if interp.step_bytecodes:
_break() # Continue stepping from here to get to the current bytecode execution
return meth
More information about the pypy-commit
mailing list