Skip to content

Commit 05d52c7

Browse files
committed
Change logic for resizing stack; top_of_stack is now a Gen
1 parent 1907cbb commit 05d52c7

File tree

4 files changed

+55
-35
lines changed

4 files changed

+55
-35
lines changed

cypari2/handle_error.pyx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ from cysignals.signals cimport sig_block, sig_unblock, sig_error
2929

3030
from .paridecl cimport *
3131
from .paripriv cimport *
32-
from .stack cimport clone_gen_noclear, reset_avma
32+
from .stack cimport clone_gen_noclear, reset_avma, after_resize
3333

3434

3535
# We derive PariError from RuntimeError, for backward compatibility with
@@ -222,9 +222,10 @@ cdef void _pari_err_recover(long errnum):
222222
reset_avma()
223223

224224
# Special case errnum == -1 corresponds to a reallocation of the
225-
# PARI stack. This is not an error, so just proceed as if nothing
226-
# happened.
225+
# PARI stack. This is not an error, so call after_resize() and
226+
# proceed as if nothing happened.
227227
if errnum < 0:
228+
after_resize()
228229
return
229230

230231
# An exception was raised. Jump to the signal-handling code

cypari2/pari_instance.pyx

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ from .string_utils cimport to_string, to_bytes
287287
from .paridecl cimport *
288288
from .paripriv cimport *
289289
from .gen cimport Gen, objtogen
290-
from .stack cimport (new_gen, new_gen_noclear,
291-
clear_stack, move_gens_to_heap)
290+
from .stack cimport (new_gen, new_gen_noclear, clear_stack,
291+
set_pari_stack_size, before_resize, after_resize)
292292
from .handle_error cimport _pari_init_error_handling
293293
from .closure cimport _pari_init_closure
294294

@@ -472,16 +472,6 @@ cdef void python_flush():
472472
include 'auto_instance.pxi'
473473

474474

475-
cdef int set_pari_stack_size(size_t size, size_t sizemax) except -1:
476-
"""
477-
Safely set the PARI stack size
478-
"""
479-
move_gens_to_heap(-1)
480-
sig_on()
481-
paristack_setsize(size, sizemax)
482-
sig_off()
483-
484-
485475
cdef class Pari(Pari_auto):
486476
def __cinit__(self):
487477
r"""
@@ -502,6 +492,7 @@ cdef class Pari(Pari_auto):
502492
# Take 1MB as minimal stack. Use maxprime=0, which PARI will
503493
# internally increase to some small value like 65537.
504494
pari_init_opts(1000000, 0, INIT_DFTm)
495+
after_resize()
505496

506497
# Disable PARI's stack overflow checking which is incompatible
507498
# with multi-threading.
@@ -1413,21 +1404,19 @@ cdef long get_var(v) except -2:
14131404
return varno
14141405

14151406

1416-
# Monkey-patched versions of default(parisize) and default(parisizemax).
1417-
# We need to call move_gens_to_heap(-1) before reallocating the PARI
1418-
# stack. The monkey-patching is set up in PariInstance.__cinit__
1407+
# Monkey-patched versions of default(parisize) and default(parisizemax)
1408+
# which call before_resize() and after_resize().
1409+
# The monkey-patching is set up in PariInstance.__cinit__
14191410
cdef GEN patched_parisize(const char* v, long flag):
1420-
try:
1421-
move_gens_to_heap(-1)
1422-
except:
1411+
# Cast to int(*)() to avoid exception handling
1412+
if (<int(*)()>before_resize)():
14231413
sig_error()
14241414
return sd_parisize(v, flag)
14251415

14261416

14271417
cdef GEN patched_parisizemax(const char* v, long flag):
1428-
try:
1429-
move_gens_to_heap(-1)
1430-
except:
1418+
# Cast to int(*)() to avoid exception handling
1419+
if (<int(*)()>before_resize)():
14311420
sig_error()
14321421
return sd_parisizemax(v, flag)
14331422

cypari2/stack.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ cdef void reset_avma()
1414
cdef void remove_from_pari_stack(Gen self)
1515
cdef int move_gens_to_heap(pari_sp lim) except -1
1616

17+
cdef int before_resize() except -1
18+
cdef int set_pari_stack_size(size_t size, size_t sizemax) except -1
19+
cdef void after_resize()
20+
1721

1822
cdef class DetachGen:
1923
cdef source

cypari2/stack.pyx

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ from cysignals.memory cimport check_malloc, sig_free
2727
from .gen cimport Gen, Gen_new
2828
from .paridecl cimport (avma, pari_mainstack, gnil, gcopy,
2929
is_universal_constant, is_on_stack,
30-
isclone, gclone, gclone_refc)
30+
isclone, gclone, gclone_refc,
31+
paristack_setsize)
3132

3233
from warnings import warn
3334

@@ -38,7 +39,7 @@ cdef extern from *:
3839

3940

4041
# Singleton object to denote the top of the PARI stack
41-
cdef object top_of_stack = object()
42+
cdef Gen top_of_stack = Gen_new(gnil, NULL)
4243

4344
# Pointer to the Gen on the bottom of the PARI stack. This is the first
4445
# element of the Gen linked list. If the linked list is empty, this
@@ -84,11 +85,10 @@ cdef inline Gen Gen_stack_new(GEN x):
8485
z = Gen_new(x, <GEN>avma)
8586
z.next = n
8687
stackbottom = <PyObject*>z
87-
if n is not top_of_stack:
88-
sz = z.sp()
89-
sn = n.sp()
90-
if sz > sn:
91-
raise SystemError(f"objects on PARI stack in invalid order (first: 0x{sz:x}; next: 0x{sn:x})")
88+
sz = z.sp()
89+
sn = n.sp()
90+
if sz > sn:
91+
raise SystemError(f"objects on PARI stack in invalid order (first: 0x{sz:x}; next: 0x{sn:x})")
9292
return z
9393

9494

@@ -102,10 +102,7 @@ cdef void reset_avma():
102102
# NOTE: this can be called with an exception set (the error handler
103103
# does that)!
104104
global avma
105-
if stackbottom is <PyObject*>top_of_stack:
106-
avma = pari_mainstack.top
107-
else:
108-
avma = (<Gen>stackbottom).sp()
105+
avma = (<Gen>stackbottom).sp()
109106

110107

111108
cdef void clear_stack():
@@ -142,6 +139,35 @@ cdef int move_gens_to_heap(pari_sp lim) except -1:
142139
current.address = current.g
143140

144141

142+
cdef int before_resize() except -1:
143+
"""
144+
Prepare for resizing the PARI stack
145+
146+
This must be called before reallocating the PARI stack
147+
"""
148+
move_gens_to_heap(-1)
149+
if top_of_stack.sp() != pari_mainstack.top:
150+
raise RuntimeError("cannot resize PARI stack here")
151+
152+
153+
cdef int set_pari_stack_size(size_t size, size_t sizemax) except -1:
154+
"""
155+
Safely set the PARI stack size
156+
"""
157+
before_resize()
158+
sig_on()
159+
paristack_setsize(size, sizemax)
160+
sig_off()
161+
after_resize()
162+
163+
164+
cdef void after_resize():
165+
"""
166+
This must be called after reallocating the PARI stack
167+
"""
168+
top_of_stack.address = <GEN>pari_mainstack.top
169+
170+
145171
cdef Gen new_gen(GEN x):
146172
"""
147173
Create a new ``Gen`` from a ``GEN``. Except if `x` is ``gnil``, then

0 commit comments

Comments
 (0)