Author: Lars Wassermann <lars.wasserm...@gmail.com>
Branch: 
Changeset: r398:db177965782f
Date: 2013-05-21 15:55 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/db177965782f/

Log:    changed context part shadow to raise an SendersChainManipulated-
        Exception when assigning to _s_sender that error need be catched in
        different places, and only when caught by the
        doubleExtendedDoAnything bytecode, drop the c-stack...

        tested

diff --git a/spyvm/constants.py b/spyvm/constants.py
--- a/spyvm/constants.py
+++ b/spyvm/constants.py
@@ -97,7 +97,7 @@
 SO_A_POINT = 33
 SO_CANNOT_INTERPRET = 34
 SO_A_METHODCONTEXT = 35 # deprecated in closure images
-SO_BLOCKCLOSURE_CLASS = 36 
+SO_BLOCKCLOSURE_CLASS = 36
 SO_A_BLOCKCONTEXT = 37 # deprecated in closure images
 SO_EXTERNAL_OBJECTS_ARRAY = 38
 SO_PSEUDOCONTEXT_CLASS = 39
diff --git a/spyvm/error.py b/spyvm/error.py
--- a/spyvm/error.py
+++ b/spyvm/error.py
@@ -29,3 +29,7 @@
 class Exit(Exception):
     def __init__(self, msg):
         self.msg = msg
+
+class SenderChainManipulation(Exception):
+    def __init__(self, manipulated_context):
+        self.s_context = manipulated_context
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -503,6 +503,7 @@
         return self._sendSelfSelector(w_selector, argcount, interp)
 
     def doubleExtendedDoAnythingBytecode(self, interp, current_bytecode):
+        from spyvm import error
         second = self.getbytecode()
         third = self.getbytecode()
         opType = second >> 5
@@ -526,9 +527,15 @@
             association = wrapper.AssociationWrapper(self.space, w_association)
             self.push(association.value())
         elif opType == 5:
-            self.w_receiver().store(self.space, third, self.top())
+            try:
+                self.w_receiver().store(self.space, third, self.top())
+            except error.SenderChainManipulation, e:
+                raise StackOverflow(self)
         elif opType == 6:
-            self.w_receiver().store(self.space, third, self.pop())
+            try:
+                self.w_receiver().store(self.space, third, self.pop())
+            except error.SenderChainManipulation, e:
+                raise StackOverflow(self)
         elif opType == 7:
             w_association = self.s_method().getliteral(third)
             association = wrapper.AssociationWrapper(self.space, w_association)
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -1144,9 +1144,13 @@
     return s_new_context.w_self()
 
 def finalize_block_ctx(interp, s_block_ctx, s_frame):
+    from spyvm.error import SenderChainManipulation
     # Set some fields
     s_block_ctx.store_pc(s_block_ctx.initialip())
-    s_block_ctx.store_s_sender(s_frame)
+    try:
+        s_block_ctx.store_s_sender(s_frame)
+    except SenderChainManipulation, e:
+        assert e.s_context == s_block_ctx
     return s_block_ctx
 
 @expose_primitive(VALUE, result_is_new_frame=True)
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -417,7 +417,10 @@
         w_self = self.w_self()
         assert isinstance(w_self, model.W_PointersObject)
         for i in range(self._w_self_size):
-            self.copy_from_w_self(i)
+            try:
+                self.copy_from_w_self(i)
+            except error.SenderChainManipulation, e:
+                assert e.s_context == self
         w_self._vars = None
 
     # def detach_shadow(self):
@@ -530,13 +533,14 @@
     def store_s_sender(self, s_sender):
         assert s_sender is None or isinstance(s_sender, ContextPartShadow)
         self._s_sender = s_sender
+        raise error.SenderChainManipulation(self)
 
     def store_w_sender(self, w_sender):
         assert isinstance(w_sender, model.W_PointersObject)
         if w_sender.is_same_object(self.space.w_nil):
             self._s_sender = None
         else:
-            self._s_sender = w_sender.as_context_get_shadow(self.space)
+            self.store_s_sender(w_sender.as_context_get_shadow(self.space))
 
     def w_sender(self):
         if self._s_sender is None:
@@ -572,7 +576,10 @@
 
     def mark_returned(self):
         self.store_pc(-1)
-        self.store_s_sender(None)
+        try:
+            self.store_s_sender(None)
+        except error.SenderChainManipulation, e:
+            assert self == e.s_context
 
     def is_returned(self):
         return self.pc() == -1 and self.w_sender is self.space.w_nil
@@ -851,7 +858,10 @@
 
         s_new_context.store_w_method(s_method.w_self())
         if s_sender:
-            s_new_context.store_s_sender(s_sender)
+            try:
+                s_new_context.store_s_sender(s_sender)
+            except error.SenderChainManipulation, e:
+                assert s_new_context == e.s_context
         s_new_context.store_w_receiver(w_receiver)
         s_new_context.store_pc(pc)
         s_new_context.init_stack_and_temps()
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -1041,3 +1041,11 @@
         assert space.unwrap_int(e.object) == 68
     except interpreter.StackOverflow, e:
         assert False
+
+def test_c_stack_reset_on_sender_chain_manipulation():
+    import operator
+    bytes = reduce(operator.add, map(chr, [0x84, 0xc0, 0x00]))
+    w_frame, s_frame = new_frame(bytes)
+    s_frame.store_w_receiver(w_frame)
+    s_frame.push(w_frame)
+    py.test.raises(interpreter.StackOverflow, step_in_interp, s_frame)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to