Skip to content

Commit 81d9b32

Browse files
committed
scope.c - rework SSGROW() and SSCHECK() macros and undelying functions
Prior to this patch SSCHECK() took a "needs" parameter, but did not actually guarantee that the stack would be sufficiently large to accomodate that many elements after the call. This was quite misleading. Especially as SSGROW() would not do geometric preallocation, but SSCHECK() would, so much of the time SSCHECK() would appear to be a better choice, but not always. This patch makes it so SSCHECK() is an alias for SSGROW(), and it makes it so that SSGROW() also geometrically overallocates. The underlying function that used to implement SSCHECK() savestack_grow() now calls the savestack_grow_cnt() which has always implemented SSGROW(). Anything in the internals that used to call SSCHECK() now calls SSGROW() instead. At the same time the preallocation has been made a little bit more aggressive, ensuring that we always allocate at least SS_MAXPUSH elements on top of what was requested as part of the "known" size of the stack, and additional SS_MAXPUSH elements which are not part of the "known" size of the stack. This "hidden extra" is used to simply some of the other macros which are used a lot internally. (I have beefed up the comment explaining this as well.) See #20530 where Dave M points out the problem with this logic. Currently I don't think we have a good way to test for the error that he showed so unfortunately this patch lacks a test.
1 parent d6a7165 commit 81d9b32

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

regexec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen _pDEPTH)
262262
);
263263
);
264264

265-
SSCHECK(total_elems + REGCP_FRAME_ELEMS);
265+
SSGROW(total_elems + REGCP_FRAME_ELEMS);
266266

267267
/* memcpy the offs inside the stack - it's faster than for loop */
268268
memcpy(&PL_savestack[PL_savestack_ix], rex->offs + parenfloor + 1, paren_bytes_to_push);

scope.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ Perl_stack_grow(pTHX_ SV **sp, SV **p, SSize_t n)
6363
return PL_stack_sp;
6464
}
6565

66-
#ifndef STRESS_REALLOC
67-
#define GROW(old) ((old) * 3 / 2)
68-
#else
66+
#ifdef STRESS_REALLOC
6967
#define GROW(old) ((old) + 1)
68+
#else
69+
#define GROW(old) ((old) * 3 / 2)
7070
#endif
7171

7272
PERL_SI *
@@ -166,25 +166,30 @@ Perl_markstack_grow(pTHX)
166166
void
167167
Perl_savestack_grow(pTHX)
168168
{
169-
IV new_max;
169+
IV by = PL_savestack_max - PL_savestack_ix;
170170
#ifdef STRESS_REALLOC
171-
new_max = PL_savestack_max + SS_MAXPUSH;
172-
#else
173-
new_max = GROW(PL_savestack_max);
171+
by += SS_MAXPUSH;
174172
#endif
175-
/* Note that we allocate SS_MAXPUSH slots higher than ss_max
176-
* so that SS_ADD_END(), SSGROW() etc can do a simper check */
177-
Renew(PL_savestack, new_max + SS_MAXPUSH, ANY);
178-
PL_savestack_max = new_max;
173+
Perl_savestack_grow_cnt(aTHX_ by);
179174
}
180175

181176
void
182177
Perl_savestack_grow_cnt(pTHX_ I32 need)
183178
{
184-
const IV new_max = PL_savestack_ix + need;
185-
/* Note that we allocate SS_MAXPUSH slots higher than ss_max
186-
* so that SS_ADD_END(), SSGROW() etc can do a simper check */
187-
Renew(PL_savestack, new_max + SS_MAXPUSH, ANY);
179+
/* Add what they ask for, plus at least SS_MAXPUSH (currently 4) */
180+
const IV new_max_floor = PL_savestack_ix + need + SS_MAXPUSH;
181+
/* and then multiply the whole thing by 1.5 */
182+
const IV new_max = GROW(new_max_floor);
183+
184+
/* Note that we add an additional SS_MAXPUSH slots on top of
185+
* PL_savestack_max so that SS_ADD_END(), SSGROW() etc can do
186+
* a simper check and if necessary realloc *after* apparently
187+
* overwriting the current PL_savestack_max. See scope.h.
188+
*
189+
* The +1 is because new_max/PL_savestack_max is the highest
190+
* index, by Renew needs the number of items, which is one
191+
* larger than the highest index. */
192+
Renew(PL_savestack, new_max + SS_MAXPUSH + 1, ANY);
188193
PL_savestack_max = new_max;
189194
}
190195

@@ -633,7 +638,7 @@ Perl_save_iv(pTHX_ IV *ivp)
633638
{
634639
PERL_ARGS_ASSERT_SAVE_IV;
635640

636-
SSCHECK(3);
641+
SSGROW(3);
637642
SSPUSHIV(*ivp);
638643
SSPUSHPTR(ivp);
639644
SSPUSHUV(SAVEt_IV);

scope.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
* macros */
2828
#define SS_MAXPUSH 4
2929

30-
#define SSCHECK(need) if (UNLIKELY(PL_savestack_ix + (I32)(need) > PL_savestack_max)) savestack_grow()
3130
#define SSGROW(need) if (UNLIKELY(PL_savestack_ix + (I32)(need) > PL_savestack_max)) savestack_grow_cnt(need)
31+
#define SSCHECK(need) SSGROW(need) /* legacy */
3232
#define SSPUSHINT(i) (PL_savestack[PL_savestack_ix++].any_i32 = (I32)(i))
3333
#define SSPUSHLONG(i) (PL_savestack[PL_savestack_ix++].any_long = (long)(i))
3434
#define SSPUSHBOOL(p) (PL_savestack[PL_savestack_ix++].any_bool = (p))
@@ -47,7 +47,7 @@
4747
* like save_pushptrptr() to half its former size.
4848
* Of course, doing the size check *after* pushing means we must always
4949
* ensure there are SS_MAXPUSH free slots on the savestack. This is ensured by
50-
* savestack_grow() and savestack_grow_cnt always allocating SS_MAXPUSH slots
50+
* savestack_grow_cnt always allocating SS_MAXPUSH slots
5151
* more than asked for, or that it sets PL_savestack_max to
5252
*
5353
* These are for internal core use only and are subject to change */
@@ -61,7 +61,7 @@
6161
ix += (need); \
6262
PL_savestack_ix = ix; \
6363
assert(ix <= PL_savestack_max + SS_MAXPUSH); \
64-
if (UNLIKELY(ix > PL_savestack_max)) savestack_grow(); \
64+
if (UNLIKELY(ix > PL_savestack_max)) savestack_grow_cnt(ix - PL_savestack_max); \
6565
assert(PL_savestack_ix <= PL_savestack_max);
6666

6767
#define SS_ADD_INT(i) ((ssp++)->any_i32 = (I32)(i))

0 commit comments

Comments
 (0)