[pypy-svn] r73087 - in pypy/branch/stackovf/pypy: interpreter interpreter/test rlib rpython

arigo at codespeak.net arigo at codespeak.net
Mon Mar 29 17:33:41 CEST 2010


Author: arigo
Date: Mon Mar 29 17:33:33 2010
New Revision: 73087

Modified:
   pypy/branch/stackovf/pypy/interpreter/gateway.py
   pypy/branch/stackovf/pypy/interpreter/pyopcode.py
   pypy/branch/stackovf/pypy/interpreter/test/test_interpreter.py
   pypy/branch/stackovf/pypy/rlib/rstackovf.py
   pypy/branch/stackovf/pypy/rpython/llinterp.py
Log:
Use StackOverflow in the PyPy interpreter.  Reduce the multiple duplication
of exception-catching code in gateway.py by factoring it in a helper
(and too bad if it's marginally slower).


Modified: pypy/branch/stackovf/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/stackovf/pypy/interpreter/gateway.py	(original)
+++ pypy/branch/stackovf/pypy/interpreter/gateway.py	Mon Mar 29 17:33:33 2010
@@ -22,6 +22,7 @@
 from pypy.interpreter.argument import Arguments, Signature
 from pypy.tool.sourcetools import NiceCompile, compile2
 from pypy.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
+from pypy.rlib import rstackovf
 
 # internal non-translatable parts: 
 import py
@@ -548,27 +549,32 @@
                                  func.defs_w, self.minargs)
         try:
             w_result = activation._run(space, scope_w)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt,
-                                 space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e)))
-        except DescrMismatch, e:
+        except DescrMismatch:
             if w_obj is not None:
                 args = args.prepend(w_obj)
             return scope_w[0].descr_call_mismatch(space,
                                                   self.descrmismatch_op,
                                                   self.descr_reqcls,
                                                   args)
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
 
+    def handle_exception(self, e):
+        try:
+            raise e
+        except KeyboardInterrupt: 
+            raise OperationError(space.w_KeyboardInterrupt,
+                                 space.w_None) 
+        except MemoryError: 
+            raise OperationError(space.w_MemoryError, space.w_None)
+        except rstackovf.StackOverflow, e:
+            rstackovf.check_stack_overflow(e)
+            raise OperationError(space.w_RuntimeError,
+                                space.wrap("maximum recursion depth exceeded"))
+
 # (verbose) performance hack below
 
 class BuiltinCodePassThroughArguments0(BuiltinCode):
@@ -578,20 +584,13 @@
         space = func.space
         try:
             w_result = self.func__args__(space, args)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e))) 
-        except DescrMismatch, e:
+        except DescrMismatch:
             return args.firstarg().descr_call_mismatch(space,
                                                   self.descrmismatch_op,
                                                   self.descr_reqcls,
                                                   args)
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -604,20 +603,13 @@
         space = func.space
         try:
             w_result = self.func__args__(space, w_obj, args)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e))) 
-        except DescrMismatch, e:
+        except DescrMismatch:
             return args.firstarg().descr_call_mismatch(space,
                                                   self.descrmismatch_op,
                                                   self.descr_reqcls,
                                                   args.prepend(w_obj))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -629,15 +621,11 @@
     def fastcall_0(self, space, w_func):
         try:
             w_result = self.fastfunc_0(space)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except (RuntimeError, DescrMismatch), e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e))) 
+        except DescrMismatch:
+            raise OperationError(space.w_SystemError,
+                                 space.wrap("unexpected DescrMismatch error"))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -649,20 +637,13 @@
     def fastcall_1(self, space, w_func, w1):
         try:
             w_result = self.fastfunc_1(space, w1)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e)))
-        except DescrMismatch, e:
+        except DescrMismatch:
             return  w1.descr_call_mismatch(space,
                                            self.descrmismatch_op,
                                            self.descr_reqcls,
                                            Arguments(space, [w1]))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -674,20 +655,13 @@
     def fastcall_2(self, space, w_func, w1, w2):
         try:
             w_result = self.fastfunc_2(space, w1, w2)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e))) 
-        except DescrMismatch, e:
+        except DescrMismatch:
             return  w1.descr_call_mismatch(space,
                                            self.descrmismatch_op,
                                            self.descr_reqcls,
                                            Arguments(space, [w1, w2]))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -699,20 +673,13 @@
     def fastcall_3(self, space, func, w1, w2, w3):
         try:
             w_result = self.fastfunc_3(space, w1, w2, w3)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e)))
-        except DescrMismatch, e:
+        except DescrMismatch:
             return  w1.descr_call_mismatch(space,
                                            self.descrmismatch_op,
                                            self.descr_reqcls,
                                            Arguments(space, [w1, w2, w3]))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result
@@ -724,21 +691,14 @@
     def fastcall_4(self, space, func, w1, w2, w3, w4):
         try:
             w_result = self.fastfunc_4(space, w1, w2, w3, w4)
-        except KeyboardInterrupt: 
-            raise OperationError(space.w_KeyboardInterrupt, space.w_None) 
-        except MemoryError: 
-            raise OperationError(space.w_MemoryError, space.w_None)
-        except NotImplementedError, e:
-            raise
-        except RuntimeError, e: 
-            raise OperationError(space.w_RuntimeError, 
-                                 space.wrap("internal error: " + str(e)))
-        except DescrMismatch, e:
+        except DescrMismatch:
             return  w1.descr_call_mismatch(space,
                                            self.descrmismatch_op,
                                            self.descr_reqcls,
                                            Arguments(space,
                                                      [w1, w2, w3, w4]))
+        except Exception, e:
+            raise self.handle_exception(e)
         if w_result is None:
             w_result = space.w_None
         return w_result

Modified: pypy/branch/stackovf/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/stackovf/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/stackovf/pypy/interpreter/pyopcode.py	Mon Mar 29 17:33:33 2010
@@ -18,6 +18,7 @@
 from pypy.tool.stdlib_opcode import unrolling_opcode_descs
 from pypy.tool.stdlib_opcode import opcode_method_names
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib import rstackovf
 
 def unaryoperation(operationname):
     """NOT_RPYTHON"""
@@ -106,20 +107,13 @@
         except MemoryError:
             next_instr = self.handle_asynchronous_error(ec,
                 self.space.w_MemoryError)
-        except NotImplementedError:
-            raise
-        except RuntimeError, e:
-            if we_are_translated():
-                # stack overflows should be the only kind of RuntimeErrors
-                # in translated PyPy
-                msg = "internal error (stack overflow?)"
-            else:
-                msg = str(e)
+        except rstackovf.StackOverflow, e:
+            rstackovf.check_stack_overflow(e)
             next_instr = self.handle_asynchronous_error(ec,
                 self.space.w_RuntimeError,
-                self.space.wrap(msg))
+                self.space.wrap("maximum recursion depth exceeded"))
         return next_instr
-        
+
     def handle_asynchronous_error(self, ec, w_type, w_value=None):
         # catch asynchronous exceptions and turn them
         # into OperationErrors

Modified: pypy/branch/stackovf/pypy/interpreter/test/test_interpreter.py
==============================================================================
--- pypy/branch/stackovf/pypy/interpreter/test/test_interpreter.py	(original)
+++ pypy/branch/stackovf/pypy/interpreter/test/test_interpreter.py	Mon Mar 29 17:33:33 2010
@@ -263,3 +263,12 @@
     def test_identity(self):
         def f(x): return x
         assert f(666) == 666
+
+    def test_raise_recursion(self):
+        def f(): f()
+        try:
+            f()
+        except RuntimeError, e:
+            assert str(e) == "maximum recursion depth exceeded"
+        else:
+            assert 0, "should have raised!"

Modified: pypy/branch/stackovf/pypy/rlib/rstackovf.py
==============================================================================
--- pypy/branch/stackovf/pypy/rlib/rstackovf.py	(original)
+++ pypy/branch/stackovf/pypy/rlib/rstackovf.py	Mon Mar 29 17:33:33 2010
@@ -1,3 +1,4 @@
+from pypy.rlib.objectmodel import we_are_translated
 
 # RPython raises StackOverflow instead of just RuntimeError when running
 # out of C stack.  We need some hacks to support "except StackOverflow:"
@@ -13,3 +14,12 @@
 
 # replace StackOverflow with this, which works in untranslated code too
 StackOverflow = ((RuntimeError, RuntimeError),)
+
+
+def check_stack_overflow(e):
+    if we_are_translated():
+        return
+    # before translation, an "except StackOverflow" includes all RuntimeErrors,
+    # including NotImplementedError.  Special-case them.
+    if type(e) is not RuntimeError or 'recursion' not in str(e):
+        raise e

Modified: pypy/branch/stackovf/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/stackovf/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/stackovf/pypy/rpython/llinterp.py	Mon Mar 29 17:33:33 2010
@@ -323,8 +323,7 @@
             if not (catch_exception and op is block.operations[-1]):
                 raise
         except RuntimeError, e:
-            if 'recursion' not in str(e):     # hack
-                raise
+            rstackovf.check_stack_overflow(e)
             # xxx fish fish fish for proper etype and evalue to use
             rtyper = self.llinterpreter.typer
             bk = rtyper.annotator.bookkeeper



More information about the Pypy-commit mailing list