[pypy-commit] pypy default: Hard to test: add rstack.stack_almost_full() and use it:

arigo pypy.commits at gmail.com
Thu Feb 2 08:35:27 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r89898:c48c3b08c41f
Date: 2017-02-02 14:34 +0100
http://bitbucket.org/pypy/pypy/changeset/c48c3b08c41f/

Log:	Hard to test: add rstack.stack_almost_full() and use it:

	* to not start JITting when the stack is almost full

	* to propagate (instead of catching) a RuntimeError caused by stack
	overflow as long as the stack is still almost full

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -7,7 +7,7 @@
 
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.rlib import rstackovf
+from rpython.rlib import rstack, rstackovf
 
 from pypy.interpreter import debug
 
@@ -55,6 +55,7 @@
         "Check if this is an exception that should better not be caught."
         return (self.match(space, space.w_SystemExit) or
                 self.match(space, space.w_KeyboardInterrupt))
+        # note: an extra case is added in OpErrFmtNoArgs
 
     def __str__(self):
         "NOT_RPYTHON: Convenience for tracebacks."
@@ -387,6 +388,16 @@
     def _compute_value(self, space):
         return self._value
 
+    def async(self, space):
+        # also matches a RuntimeError("maximum rec.") if the stack is
+        # still almost full, because in this case it might be a better
+        # idea to propagate the exception than eat it
+        if (self.w_type is space.w_RuntimeError and
+            self._value == "maximum recursion depth exceeded" and
+            rstack.stack_almost_full()):
+            return True
+        return OperationError.async(self, space)
+
 @specialize.memo()
 def get_operr_class(valuefmt):
     try:
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -88,6 +88,7 @@
                           'interp_magic.save_module_content_for_future_reload',
         'decode_long'               : 'interp_magic.decode_long',
         '_promote'                   : 'interp_magic._promote',
+        'stack_almost_full'         : 'interp_magic.stack_almost_full',
     }
     if sys.platform == 'win32':
         interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp'
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -9,7 +9,7 @@
 from pypy.objspace.std.setobject import W_BaseSetObject
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import MapAttrCache
-from rpython.rlib import rposix, rgc
+from rpython.rlib import rposix, rgc, rstack
 
 
 def internal_repr(space, w_object):
@@ -190,3 +190,7 @@
     else:
         jit.promote(w_obj)
     return w_obj
+
+def stack_almost_full(space):
+    """Return True if the stack is more than 15/16th full."""
+    return space.wrap(rstack.stack_almost_full())
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -732,7 +732,8 @@
     TY_FLOAT        = 0x06
 
     def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
-        if self.must_compile(deadframe, metainterp_sd, jitdriver_sd):
+        if (self.must_compile(deadframe, metainterp_sd, jitdriver_sd)
+                and not rstack.stack_almost_full()):
             self.start_compiling()
             try:
                 self._trace_and_compile_from_bridge(deadframe, metainterp_sd,
diff --git a/rpython/jit/metainterp/warmstate.py b/rpython/jit/metainterp/warmstate.py
--- a/rpython/jit/metainterp/warmstate.py
+++ b/rpython/jit/metainterp/warmstate.py
@@ -11,6 +11,7 @@
 from rpython.rlib.objectmodel import specialize, we_are_translated, r_dict
 from rpython.rlib.rarithmetic import intmask, r_uint
 from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib import rstack
 from rpython.rtyper.annlowlevel import (hlstr, cast_base_ptr_to_instance,
     cast_object_to_ptr)
 from rpython.rtyper.lltypesystem import lltype, llmemory, rstr, rffi
@@ -415,6 +416,8 @@
             if not confirm_enter_jit(*args):
                 return
             jitcounter.decay_all_counters()
+            if rstack.stack_almost_full():
+                return
             # start tracing
             from rpython.jit.metainterp.pyjitpl import MetaInterp
             metainterp = MetaInterp(metainterp_sd, jitdriver_sd)
diff --git a/rpython/rlib/rstack.py b/rpython/rlib/rstack.py
--- a/rpython/rlib/rstack.py
+++ b/rpython/rlib/rstack.py
@@ -69,3 +69,22 @@
         raise _StackOverflow
 stack_check_slowpath._dont_inline_ = True
 stack_check_slowpath._dont_insert_stackcheck_ = True
+
+def stack_almost_full():
+    """Return True if the stack is more than 15/16th full."""
+    if not we_are_translated():
+        return False
+    # see stack_check()
+    current = llop.stack_current(lltype.Signed)
+    end = _stack_get_end()
+    length = 15 * (r_uint(_stack_get_length()) >> 4)
+    ofs = r_uint(end - current)
+    if ofs <= length:
+        return False    # fine
+    else:
+        _stack_too_big_slowpath(current)   # this might update the stack end
+        end = _stack_get_end()
+        ofs = r_uint(end - current)
+        return ofs > length
+stack_almost_full._dont_insert_stackcheck_ = True
+stack_almost_full._jit_look_inside_ = False


More information about the pypy-commit mailing list