Skip to content

Commit bbb74e9

Browse files
Replaced recppush/regcppop with memcpy
Basically tested with Intel VTune to be increasing the performance of a perl regex matching program with multiple capture groups and recursive patterns
1 parent fd4fc0f commit bbb74e9

File tree

2 files changed

+55
-41
lines changed

2 files changed

+55
-41
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Alexander D'Archangel <darksuji@gmail.com>
6767
Alexander Foken
6868
Alexander Gernler <alexander_gernler@genua.de>
6969
Alexander Gough <alex-p5p@earth.li>
70+
Alexander Nikolov <sasho648@gmail.com>
7071
Alexander Hartmaier <abraxxa@cpan.org>
7172
Alexander Klimov <ask@wisdom.weizmann.ac.il>
7273
Alexander Smishlajev <als@turnhere.com>

regexec.c

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ static void S_setup_eval_state(pTHX_ regmatch_info *const reginfo);
218218
static void S_cleanup_regmatch_info_aux(pTHX_ void *arg);
219219
static regmatch_state * S_push_slab(pTHX);
220220

221-
#define REGCP_PAREN_ELEMS 3
222221
#define REGCP_OTHER_ELEMS 3
223222
#define REGCP_FRAME_ELEMS 1
224223
/* REGCP_FRAME_ELEMS are not part of the REGCP_OTHER_ELEMS and
@@ -228,19 +227,23 @@ STATIC CHECKPOINT
228227
S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen _pDEPTH)
229228
{
230229
const int retval = PL_savestack_ix;
231-
const int paren_elems_to_push =
232-
(maxopenparen - parenfloor) * REGCP_PAREN_ELEMS;
230+
const SSize_t paren_bytes_to_push = sizeof(*rex->offs) * (maxopenparen - parenfloor);
231+
/* Number of savestack[] entries to be filled by the paren data */
232+
const int paren_elems_to_push = (paren_bytes_to_push + sizeof(*PL_savestack) - 1) / sizeof(*PL_savestack);
233233
const UV total_elems = paren_elems_to_push + REGCP_OTHER_ELEMS;
234234
const UV elems_shifted = total_elems << SAVE_TIGHT_SHIFT;
235235
I32 p;
236236
DECLARE_AND_GET_RE_DEBUG_FLAGS;
237237

238+
/* static assert that offs struc size is not less than stack elem size */
239+
STATIC_ASSERT_STMT(sizeof(*rex->offs) >= sizeof(*PL_savestack));
240+
238241
PERL_ARGS_ASSERT_REGCPPUSH;
239242

240243
if (paren_elems_to_push < 0)
241-
Perl_croak(aTHX_ "panic: paren_elems_to_push, %i < 0, maxopenparen: %i parenfloor: %i REGCP_PAREN_ELEMS: %u",
244+
Perl_croak(aTHX_ "panic: paren_elems_to_push, %i < 0, maxopenparen: %i parenfloor: %i",
242245
(int)paren_elems_to_push, (int)maxopenparen,
243-
(int)parenfloor, (unsigned)REGCP_PAREN_ELEMS);
246+
(int)parenfloor);
244247

245248
if ((elems_shifted >> SAVE_TIGHT_SHIFT) != total_elems)
246249
Perl_croak(aTHX_ "panic: paren_elems_to_push offset %" UVuf
@@ -249,31 +252,35 @@ S_regcppush(pTHX_ const regexp *rex, I32 parenfloor, U32 maxopenparen _pDEPTH)
249252
(unsigned long)maxopenparen,
250253
(long)parenfloor);
251254

252-
SSGROW(total_elems + REGCP_FRAME_ELEMS);
253-
254255
DEBUG_BUFFERS_r(
255256
if ((int)maxopenparen > (int)parenfloor)
256-
Perl_re_exec_indentf( aTHX_
257+
Perl_re_exec_indentf(aTHX_
257258
"rex=0x%" UVxf " offs=0x%" UVxf ": saving capture indices:\n",
258259
depth,
259260
PTR2UV(rex),
260261
PTR2UV(rex->offs)
261262
);
262263
);
263-
for (p = parenfloor+1; p <= (I32)maxopenparen; p++) {
264-
/* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */
265-
SSPUSHIV(rex->offs[p].end);
266-
SSPUSHIV(rex->offs[p].start);
267-
SSPUSHINT(rex->offs[p].start_tmp);
268-
DEBUG_BUFFERS_r(Perl_re_exec_indentf( aTHX_
269-
" \\%" UVuf ": %" IVdf "(%" IVdf ")..%" IVdf "\n",
270-
depth,
271-
(UV)p,
272-
(IV)rex->offs[p].start,
273-
(IV)rex->offs[p].start_tmp,
274-
(IV)rex->offs[p].end
275-
));
276-
}
264+
265+
SSGROW(total_elems + REGCP_FRAME_ELEMS);
266+
267+
/* memcpy the offs inside the stack - it's faster than for loop */
268+
memcpy(&PL_savestack[PL_savestack_ix], rex->offs + parenfloor + 1, paren_bytes_to_push);
269+
PL_savestack_ix += paren_elems_to_push;
270+
271+
DEBUG_BUFFERS_r(
272+
for (p = parenfloor + 1; p <= (I32)maxopenparen; p++) {
273+
Perl_re_exec_indentf(aTHX_
274+
" \\%" UVuf ": %" IVdf "(%" IVdf ")..%" IVdf "\n",
275+
depth,
276+
(UV)p,
277+
(IV)rex->offs[p].start,
278+
(IV)rex->offs[p].start_tmp,
279+
(IV)rex->offs[p].end
280+
);
281+
}
282+
);
283+
277284
/* REGCP_OTHER_ELEMS are pushed in any case, parentheses or no. */
278285
SSPUSHINT(maxopenparen);
279286
SSPUSHINT(rex->lastparen);
@@ -366,25 +373,31 @@ S_regcppop(pTHX_ regexp *rex, U32 *maxopenparen_p _pDEPTH)
366373
PTR2UV(rex->offs)
367374
);
368375
);
369-
paren = *maxopenparen_p;
370-
for ( ; i > 0; i -= REGCP_PAREN_ELEMS) {
371-
SSize_t tmps;
372-
rex->offs[paren].start_tmp = SSPOPINT;
373-
rex->offs[paren].start = SSPOPIV;
374-
tmps = SSPOPIV;
375-
if (paren <= rex->lastparen)
376-
rex->offs[paren].end = tmps;
377-
DEBUG_BUFFERS_r( Perl_re_exec_indentf( aTHX_
378-
" \\%" UVuf ": %" IVdf "(%" IVdf ")..%" IVdf "%s\n",
379-
depth,
380-
(UV)paren,
381-
(IV)rex->offs[paren].start,
382-
(IV)rex->offs[paren].start_tmp,
383-
(IV)rex->offs[paren].end,
384-
(paren > rex->lastparen ? "(skipped)" : ""));
385-
);
386-
paren--;
387-
}
376+
/* substract remaining elements from the stack */
377+
PL_savestack_ix -= i;
378+
379+
/* calculate number of offs/capture groups stored */
380+
i = (i * sizeof(*PL_savestack)) / sizeof(*rex->offs);
381+
382+
/* calculate paren starting point */
383+
paren = *maxopenparen_p - i + 1;
384+
385+
/* restore them */
386+
memcpy(rex->offs + paren, &PL_savestack[PL_savestack_ix], i * sizeof(*rex->offs));
387+
388+
DEBUG_BUFFERS_r(
389+
for (; paren <= *maxopenparen_p; ++paren) {
390+
DEBUG_BUFFERS_r(Perl_re_exec_indentf(aTHX_
391+
" \\%" UVuf ": %" IVdf "(%" IVdf ")..%" IVdf "%s\n",
392+
depth,
393+
(UV)paren,
394+
(IV)rex->offs[paren].start,
395+
(IV)rex->offs[paren].start_tmp,
396+
(IV)rex->offs[paren].end,
397+
(paren > rex->lastparen ? "(skipped)" : ""));
398+
);
399+
}
400+
);
388401
#if 1
389402
/* It would seem that the similar code in regtry()
390403
* already takes care of this, and in fact it is in

0 commit comments

Comments
 (0)