File: rstack.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (92 lines) | stat: -rw-r--r-- 3,613 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""
This file defines utilities for manipulating the stack in an
RPython-compliant way.  It is mainly about the stack_check() function.
"""

import py

from rpython.rlib.objectmodel import we_are_translated, fetch_translated_config
from rpython.rlib.rarithmetic import r_uint
from rpython.rlib import rgc
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.lltypesystem.lloperation import llop

# ____________________________________________________________

def llexternal(name, args, res, _callable=None):
    return rffi.llexternal(name, args, res,
                           sandboxsafe=True, _nowrapper=True,
                           _callable=_callable)

_stack_get_end = llexternal('LL_stack_get_end', [], lltype.Signed,
                            lambda: 0)
_stack_get_length = llexternal('LL_stack_get_length', [], lltype.Signed,
                               lambda: 1)
_stack_set_length_fraction = llexternal('LL_stack_set_length_fraction',
                                        [lltype.Float], lltype.Void,
                                        lambda frac: None)
_stack_too_big_slowpath = llexternal('LL_stack_too_big_slowpath',
                                     [lltype.Signed], lltype.Char,
                                     lambda cur: '\x00')
# the following is used by the JIT
_stack_get_end_adr   = llexternal('LL_stack_get_end_adr',   [], lltype.Signed)
_stack_get_length_adr= llexternal('LL_stack_get_length_adr',[], lltype.Signed)

# the following is also used by the JIT: "critical code" paths are paths in
# which we should not raise StackOverflow at all, but just ignore the stack limit
_stack_criticalcode_start = llexternal('LL_stack_criticalcode_start', [],
                                       lltype.Void, lambda: None)
_stack_criticalcode_stop = llexternal('LL_stack_criticalcode_stop', [],
                                      lltype.Void, lambda: None)

def stack_check():
    if not we_are_translated():
        return
    if fetch_translated_config().translation.reverse_debugger:
        return     # XXX for now
    #
    # Load the "current" stack position, or at least some address that
    # points close to the current stack head
    current = llop.stack_current(lltype.Signed)
    #
    # Load these variables from C code
    end = _stack_get_end()
    length = _stack_get_length()
    #
    # Common case: if 'current' is within [end-length:end], everything
    # is fine
    ofs = r_uint(end - current)
    if ofs <= r_uint(length):
        return
    #
    # Else call the slow path
    stack_check_slowpath(current)
stack_check._always_inline_ = True
stack_check._dont_insert_stackcheck_ = True

@rgc.no_collect
def stack_check_slowpath(current):
    if ord(_stack_too_big_slowpath(current)):
        from rpython.rlib.rstackovf import _StackOverflow
        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