[pypy-commit] lang-smalltalk default: (tfel, tpape) store the last context when suspending, and raise to the trampoline when switching contexts

timfel noreply at buildbot.pypy.org
Fri Mar 8 13:43:42 CET 2013


Author: Tim Felgentreff <timfelgentreff at gmail.com>
Branch: 
Changeset: r143:683631ae4a75
Date: 2013-03-08 13:11 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/683631ae4a75/

Log:	(tfel, tpape) store the last context when suspending, and raise to
	the trampoline when switching contexts

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -70,6 +70,9 @@
                     s_new_context.mark_returned()
                     s_new_context = s_sender
                 s_new_context.push(nlr.value)
+            except ProcessSwitch, p:
+                self.remaining_stack_depth = self.max_stack_depth
+                s_new_context = p.s_new_context
 
     def c_loop(self, s_context):
         # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth)
@@ -146,11 +149,17 @@
 class StackOverflow(Exception):
     def __init__(self, s_top_context):
         self.s_context = s_top_context
+
 class Return(Exception):
     def __init__(self, object, s_context):
         self.value = object
         self.s_target_context = s_context
 
+class ProcessSwitch(Exception):
+    def __init__(self, s_context):
+        self.s_new_context = s_context
+
+
 def make_call_primitive_bytecode(primitive, selector, argcount):
     def callPrimitive(self, interp, current_bytecode):
         # WARNING: this is used for bytecodes for which it is safe to
diff --git a/spyvm/test/test_wrapper.py b/spyvm/test/test_wrapper.py
--- a/spyvm/test/test_wrapper.py
+++ b/spyvm/test/test_wrapper.py
@@ -144,11 +144,13 @@
 
     def test_suspend_active(self):
         process, old_process = self.make_processes(4, 2, space.w_false)
-        old_process.suspend(space.w_true)
+        w_fake_context = model.W_Object()
+        old_process.suspend(w_fake_context)
         process_list = wrapper.scheduler(space).get_process_list(old_process.priority())
         assert process_list.first_link() is process_list.last_link()
         assert process_list.first_link() is space.w_nil
         assert old_process.my_list() is space.w_nil
+        assert old_process.suspended_context() is w_fake_context
         assert wrapper.scheduler(space).active_process() is process._w_self
 
     def new_process_consistency(self, process, old_process, w_active_context,
@@ -181,7 +183,7 @@
 
     def test_activate(self):
         process, old_process = self.make_processes(4, 2, space.w_false)
-        w_frame = process.activate(space.w_true)
+        w_frame = process.activate()
         self.new_process_consistency(process, old_process, w_frame,
                                          space.w_true, space.w_false)
 
diff --git a/spyvm/wrapper.py b/spyvm/wrapper.py
--- a/spyvm/wrapper.py
+++ b/spyvm/wrapper.py
@@ -71,13 +71,15 @@
         process_list = sched.get_process_list(priority)
         process_list.add_process(self._w_self)
 
-    def activate(self, w_current_frame):
+    def activate(self):
+        from spyvm.interpreter import ProcessSwitch
+        assert not self.is_active_process()
         sched = scheduler(self.space)
         sched.store_active_process(self._w_self)
         w_frame = self.suspended_context()
         self.store_suspended_context(self.space.w_nil)
         self.store_my_list(self.space.w_nil)
-        return w_frame
+        raise ProcessSwitch(w_frame.as_context_get_shadow(self.space))
 
     def deactivate(self, w_current_frame):
         self.put_to_sleep()
@@ -90,7 +92,7 @@
         priority = self.priority()
         if priority > active_priority:
             active_process.deactivate(w_current_frame)
-            return self.activate(w_current_frame)
+            return self.activate()
         else:
             self.put_to_sleep()
             return w_current_frame
@@ -102,7 +104,8 @@
         if self.is_active_process():
             assert self.my_list().is_same_object(self.space.w_nil)
             w_process = scheduler(self.space).highest_priority_process()
-            return ProcessWrapper(self.space, w_process).activate(w_current_frame)
+            self.store_suspended_context(w_current_frame)
+            return ProcessWrapper(self.space, w_process).activate()
         else:
             process_list = ProcessListWrapper(self.space, self.my_list())
             process_list.remove(self._w_self)


More information about the pypy-commit mailing list