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