Commit d5e3300deb for perl
commit d5e3300deb9e41357fffaa5f30ac04b81a93a6ba
Author: Richard Leach <rich+perl@hyphen-dash-hyphen.info>
Date: Sun Oct 25 23:50:21 2026 +0000
Regex: Pre-calculate any start class length for re_intuit_start
This replaces the following per-execution calculation:
/* XXX this value could be pre-computed */
const SSize_t cl_l = (REGNODE_TYPE(OP(progi->regstclass)) == EXACT
? (reginfo->is_utf8_pat
? (SSize_t)utf8_distance(str + STR_LEN(progi->regstclass), str)
: (SSize_t)STR_LEN(progi->regstclass))
: 1);
diff --git a/regcomp.c b/regcomp.c
index 90efbddd08..a817b14852 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -2343,6 +2343,19 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
if (RExC_rx->minlen < minlen)
RExC_rx->minlen = minlen;
+ /* Pre-compute the number of characters matched by a start class.
+ * For (potential) use by Perl_re_intuit_start. */
+ if (RExC_rxi->regstclass
+ && REGNODE_TYPE(OP(RExC_rxi->regstclass)) == EXACT) {
+ const regnode * const stclass = RExC_rxi->regstclass;
+ const U8 * const str = (U8 *) STRING(stclass);
+ RExC_rxi->regstclass_len = RExC_utf8
+ ? (U8) utf8_distance(str + STR_LEN(stclass), str)
+ : (U8) STR_LEN(stclass);
+ } else {
+ RExC_rxi->regstclass_len = 1;
+ }
+
if (RExC_seen & REG_RECURSE_SEEN ) {
RExC_rx->intflags |= PREGf_RECURSE_SEEN;
Newx(RExC_rx->recurse_locinput, RExC_rx->nparens + 1, char *);
@@ -14300,6 +14313,7 @@ Perl_regdupe_internal(pTHX_ REGEXP * const rx, CLONE_PARAMS *param)
reti->name_list_idx = ri->name_list_idx;
+ reti->regstclass_len = ri->regstclass_len;
reti->slc_whilem_seen = ri->slc_whilem_seen;
reti->slc = NULL; /* will be alloced if/when needed */
reti->depth = 0;
diff --git a/regcomp.h b/regcomp.h
index fac66c7fbc..47c38e7077 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -144,6 +144,9 @@ typedef struct regexp_internal {
is true, 0 means "no value" like any other
index into the data array.*/
U32 depth; /* 1 = executing; 2+ = recursing */
+ U8 regstclass_len; /* How many chars regstclass matches.
+ * variable for an EXACTish start class,
+ * otherwise set to 1. */
U8 slc_whilem_seen; /* Num of WHILEMs using super-linear cache.
Same type as FLAGS() */
struct slc_cache_item *slc; /* permanent array of super-linear cache
diff --git a/regexec.c b/regexec.c
index 89d3b19b1e..083c044dcb 100644
--- a/regexec.c
+++ b/regexec.c
@@ -1673,14 +1673,8 @@ Perl_re_intuit_start(pTHX_
* leave it to regmatch itself) */
if (progi->regstclass && REGNODE_TYPE(OP(progi->regstclass))!=TRIE) {
- const U8* const str = (U8*)STRING(progi->regstclass);
-
- /* XXX this value could be pre-computed */
- const SSize_t cl_l = (REGNODE_TYPE(OP(progi->regstclass)) == EXACT
- ? (reginfo->is_utf8_pat
- ? (SSize_t)utf8_distance(str + STR_LEN(progi->regstclass), str)
- : (SSize_t)STR_LEN(progi->regstclass))
- : 1);
+ /* number of characters the start class matches */
+ const SSize_t cl_l = (SSize_t) progi->regstclass_len;
char * endpos;
char *s;
/* latest pos that a matching float substr constrains rx start to */