Author: Anton Gulenko <anton.gule...@googlemail.com>
Branch: storage-context-state
Changeset: r921:76c81645836d
Date: 2014-07-18 15:29 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/76c81645836d/

Log:    Delaying SenderChainManipulation as much as possible. Added a
        'state' field to Context objects, can be Inactive, Active or Dirty.
        Setting the sender of an Active context makes it Dirty. When a Dirty
        context is left, SenderChainManipulation will be raised, forcing all
        remaining contexts from the stack to the heap.

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -1,6 +1,6 @@
 import py
 import os
-from spyvm.shadow import ContextPartShadow, MethodContextShadow, 
BlockContextShadow, MethodNotFound
+from spyvm.shadow import ContextPartShadow, MethodContextShadow, 
BlockContextShadow, MethodNotFound, ActiveContext, InactiveContext, DirtyContext
 from spyvm import model, constants, primitives, conftest, wrapper, objspace
 from spyvm.tool.bitmanipulation import splitter
 
@@ -118,8 +118,10 @@
             if self.is_tracing():
                 self.stack_depth += 1
             if s_frame._s_sender is None and s_sender is not None:
-                s_frame.store_s_sender(s_sender, raise_error=False)
+                s_frame.store_s_sender(s_sender)
             # Now (continue to) execute the context bytecodes
+            assert s_frame.state is InactiveContext
+            s_frame.state = ActiveContext
             self.loop_bytecodes(s_frame, may_context_switch)
         except rstackovf.StackOverflow:
             rstackovf.check_stack_overflow()
@@ -127,7 +129,11 @@
         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 step(self, context):
         bytecode = context.fetch_next_bytecode()
         for entry in UNROLLING_BYTECODE_RANGES:
@@ -755,16 +761,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)
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -636,18 +636,29 @@
     def size(self):
         return self._w_self_size
 
+class ContextState(object):
+    def __init__(self, name):
+        self.name = name
+    def __str__(self):
+        return self.name
+    def __repr__(self):
+        return self.name
+InactiveContext = ContextState("InactiveContext")
+ActiveContext = ContextState("ActiveContext")
+DirtyContext = ContextState("DirtyContext")
+
 class ContextPartShadow(AbstractRedirectingShadow):
 
     __metaclass__ = extendabletype
     _attrs_ = ['_s_sender',
             '_pc', '_temps_and_stack',
-            '_stack_ptr', 'instances_w']
+            '_stack_ptr', 'instances_w', 'state']
     repr_classname = "ContextPartShadow"
 
     _virtualizable_ = [
         '_s_sender',
         "_pc", "_temps_and_stack[*]", "_stack_ptr",
-        "_w_self", "_w_self_size"
+        "_w_self", "_w_self_size", 'state'
     ]
 
     # ______________________________________________________________________
@@ -657,13 +668,7 @@
         self._s_sender = None
         AbstractRedirectingShadow.__init__(self, space, w_self, size)
         self.instances_w = {}
-
-    def copy_field_from(self, n0, other_shadow):
-        from spyvm.interpreter import SenderChainManipulation
-        try:
-            AbstractRedirectingShadow.copy_field_from(self, n0, other_shadow)
-        except SenderChainManipulation, e:
-            assert e.s_new_context == self
+        self.state = InactiveContext
 
     def copy_from(self, other_shadow):
         # Some fields have to be initialized before the rest, to ensure 
correct initialization.
@@ -705,7 +710,7 @@
         if n0 == constants.CTXPART_SENDER_INDEX:
             assert isinstance(w_value, model.W_PointersObject)
             if w_value.is_nil(self.space):
-                self.store_s_sender(None, raise_error=False)
+                self.store_s_sender(None)
             else:
                 self.store_s_sender(w_value.as_context_get_shadow(self.space))
             return
@@ -725,12 +730,12 @@
 
     # === Sender ===
 
-    def store_s_sender(self, s_sender, raise_error=True):
+    def store_s_sender(self, s_sender):
         if s_sender is not self._s_sender:
             self._s_sender = s_sender
-            if raise_error:
-                from spyvm.interpreter import SenderChainManipulation
-                raise SenderChainManipulation(self)
+            # If new sender is None, we are just being marked as returned.
+            if s_sender is not None and self.state is ActiveContext:
+                self.state = DirtyContext
 
     def w_sender(self):
         sender = self.s_sender()
@@ -822,7 +827,7 @@
 
     def mark_returned(self):
         self.store_pc(-1)
-        self.store_s_sender(None, raise_error=False)
+        self.store_s_sender(None)
 
     def is_returned(self):
         return self.pc() == -1 and self.w_sender().is_nil(self.space)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to