[pypy-commit] pypy py3k: properly implement POP_EXCEPT as a block, instead of popping the last_exception from the stack directly in the implementation of the opcode. This fixes test_pop_exception_value. Took two days to hunt&fix :-(
antocuni
noreply at buildbot.pypy.org
Thu May 10 23:30:41 CEST 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r55015:6c1827662c80
Date: 2012-05-10 23:30 +0200
http://bitbucket.org/pypy/pypy/changeset/6c1827662c80/
Log: properly implement POP_EXCEPT as a block, instead of popping the
last_exception from the stack directly in the implementation of the
opcode. This fixes test_pop_exception_value. Took two days to
hunt&fix :-(
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -529,14 +529,9 @@
def POP_EXCEPT(self, oparg, next_instr):
assert self.space.py3k
- # on CPython, POP_EXCEPT also pops the block. Here, the block is
- # automatically popped by unrollstack()
- w_last_exception = self.popvalue()
- if not isinstance(w_last_exception, W_OperationError):
- msg = "expected an OperationError, got %s" % (
- self.space.str_w(w_last_exception))
- raise BytecodeCorruption(msg)
- self.last_exception = w_last_exception.operr
+ block = self.pop_block()
+ block.cleanup(self)
+ return
def POP_BLOCK(self, oparg, next_instr):
block = self.pop_block()
@@ -1303,6 +1298,30 @@
return r_uint(self.handlerposition)
+class ExceptHandlerBlock(FrameBlock):
+ """
+ This is a special, implicit block type which is created when entering an
+ except handler. It does not belong to any opcode
+ """
+
+ _immutable_ = True
+ _opname = 'EXCEPT_HANDLER_BLOCK' # it's not associated to any opcode
+ handling_mask = 0 # this block is never handled, only popped by POP_EXCEPT
+
+ def handle(self, frame, unroller):
+ assert False # never called
+
+ def cleanup(self, frame):
+ frame.dropvaluesuntil(self.valuestackdepth+1)
+ w_last_exception = frame.popvalue()
+ if not isinstance(w_last_exception, W_OperationError):
+ msg = "expected an OperationError, got %s" % (
+ frame.space.str_w(w_last_exception))
+ raise BytecodeCorruption(msg)
+ frame.last_exception = w_last_exception.operr
+ FrameBlock.cleanup(self, frame)
+
+
class ExceptBlock(FrameBlock):
"""An try:except: block. Stores the position of the exception handler."""
@@ -1326,6 +1345,8 @@
w_last_exception = W_OperationError(frame.last_exception)
w_last_exception = frame.space.wrap(w_last_exception)
frame.pushvalue(w_last_exception)
+ block = ExceptHandlerBlock(self, 0, frame.lastblock)
+ frame.lastblock = block
frame.pushvalue(frame.space.wrap(unroller))
frame.pushvalue(operationerr.get_w_value(frame.space))
frame.pushvalue(operationerr.w_type)
diff --git a/pypy/interpreter/test/test_raise.py b/pypy/interpreter/test/test_raise.py
--- a/pypy/interpreter/test/test_raise.py
+++ b/pypy/interpreter/test/test_raise.py
@@ -15,6 +15,13 @@
else:
raise AssertionError("exception executing else clause!")
+ def test_store_exception(self):
+ try:
+ raise ValueError
+ except Exception as e:
+ assert e
+
+
def test_args(self):
try:
raise SystemError(1, 2)
More information about the pypy-commit
mailing list