This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
study_chunk: generate ANYOFM here rather than in join_exact()
authorHugo van der Sanden <hv@crypt.org>
Thu, 16 Jan 2020 15:42:05 +0000 (15:42 +0000)
committerKarl Williamson <khw@cpan.org>
Thu, 16 Jan 2020 18:50:41 +0000 (11:50 -0700)
When we detect an EXACTFish node cannot be extended by joining with others,
and is short and simple enough, we want to replace it with ANYOFM.

Prefer to do that in the study_chunk() handling of EXACTFish nodes: this
isn't part of join_exact's responsibilities (and is not documented there),
and moving it will make subsequent refactoring easier.

Note that this means it will no longer happen earlier as part of the
experimental regtail_study() call to join_exact(), currently invoked
only if perl is built with PERL_ENABLE_EXPERIMENTAL_REGEX_OPTIMISATIONS.

regcomp.c

index 008b8ff..733c13b 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -4422,23 +4422,6 @@ S_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
            }
 #endif
        }
-
-        if (     STR_LEN(scan) == 1
-            &&   isALPHA_A(* STRING(scan))
-            &&  (         OP(scan) == EXACTFAA
-                 || (     OP(scan) == EXACTFU
-                     && ! HAS_NONLATIN1_SIMPLE_FOLD_CLOSURE(* STRING(scan)))))
-        {
-            U8 mask = ~ ('A' ^ 'a'); /* These differ in just one bit */
-
-            /* Replace a length 1 ASCII fold pair node with an ANYOFM node,
-             * with the mask set to the complement of the bit that differs
-             * between upper and lower case, and the lowest code point of the
-             * pair (which the '&' forces) */
-            OP(scan) = ANYOFM;
-            ARG_SET(scan, *STRING(scan) & mask);
-            FLAGS(scan) = mask;
-        }
     }
 
 #ifdef DEBUGGING
@@ -5289,6 +5272,25 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
            SSize_t bytelen = STR_LEN(scan), charlen;
             const U8 * s = (U8*)STRING(scan);
 
+            /* Replace a length 1 ASCII fold pair node with an ANYOFM node,
+             * with the mask set to the complement of the bit that differs
+             * between upper and lower case, and the lowest code point of the
+             * pair (which the '&' forces) */
+            if (     bytelen == 1
+                &&   isALPHA_A(*s)
+                &&  (         OP(scan) == EXACTFAA
+                     || (     OP(scan) == EXACTFU
+                         && ! HAS_NONLATIN1_SIMPLE_FOLD_CLOSURE(*s))))
+            {
+                U8 mask = ~ ('A' ^ 'a'); /* These differ in just one bit */
+
+                OP(scan) = ANYOFM;
+                ARG_SET(scan, *s & mask);
+                FLAGS(scan) = mask;
+                /* we're not EXACTFish any more, so restudy */
+                continue;
+            }
+
            /* Search for fixed substrings supports EXACT only. */
            if (flags & SCF_DO_SUBSTR) {
                assert(data);