Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit