Collapse regnode EXACTFU_SS into EXACTFUP
authorKarl Williamson <khw@cpan.org>
Wed, 19 Dec 2018 18:21:28 +0000 (11:21 -0700)
committerKarl Williamson <khw@cpan.org>
Wed, 26 Dec 2018 19:50:37 +0000 (12:50 -0700)
EXACTFUP was created by the previous commit to handle a problematic case
in which not all the code points in an EXACTFU node are /i foldable at
compile time.  Doing so will allow a future commit to use the pre-folded
EXACTFU nodes (done in a prior commit), saving execution time for the
common case.  The only problematic code point is the MICRO SIGN.  Most
patterns don't use this character.

EXACTFU_SS is problematic in a different way.  It contains the sequence
'ss' which is folded to by LATIN SMALL LETTER SHARP S, but everything in
it can be pre-folded (unless it also contains a MICRO SIGN).  The reason
this is problematic is that it is the only non-UTF-8 node where the
length in folding can change.  To process it at runtime, the more
general fold equivalence function is used that is capable of handling
length disparities, but is slower than the functions otherwise used for
non-UTF-8.

What I've chosen to do for now is to make a single node type for all the
problematic cases (which at this time means just the two aforementioned
ones).  If we didn't do this, we'd have to add a third node type for
patterns that contain both 'ss' and MICRO.  Or artificially split the
pattern so the two never were in the same node, but we can't do that
because it can cause bugs in handling multi-character folds.  If more
special handling is found to be needed, there'd be a combinatorial
explosion of additional node types to handle all possible combinations.

What this effectively means is that the slower, more general foldEQ
function is used for portions of patterns containing the MICRO sign when
the pattern isn't in UTF-8, even though there is no inherent reason to
do so for non-UTF-8 strings that don't also contain the 'ss' sequence.

pod/perldebguts.pod
regcomp.c
regcomp.sym
regexec.c
regnodes.h

index 0c32c9a..100df82 100644 (file)
@@ -666,9 +666,6 @@ will be lost.
                              (string folded iff in UTF-8; non-UTF8
                              folded length <= unfolded).
 
- EXACTFU_SS       str        Match this string using /iu rules (w/len);
-                             (string not UTF-8, only portions guaranteed
-                             to be folded; folded length > unfolded).
  EXACTFUP         str        Match this string using /iu rules (w/len);
                              (string not UTF-8, not guaranteed to be
                              folded; and its Problematic).
index 2a94961..83c08dd 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -2653,7 +2653,7 @@ S_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
     switch (flags) {
         case EXACT: case EXACT_ONLY8: case EXACTL: break;
        case EXACTFAA:
-        case EXACTFU_SS:
+        case EXACTFUP:
        case EXACTFU:
        case EXACTFLU8: folder = PL_fold_latin1; break;
        case EXACTF:  folder = PL_fold; break;
@@ -2744,7 +2744,7 @@ S_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
             && (    OP(noper) == flags
                 || (flags == EXACT && OP(noper) == EXACT_ONLY8)
                 || (flags == EXACTFU && (   OP(noper) == EXACTFU_ONLY8
-                                         || OP(noper) == EXACTFU_SS))) )
+                                         || OP(noper) == EXACTFUP))))
         {
             uc= (U8*)STRING(noper);
             e= uc + STR_LEN(noper);
@@ -2757,7 +2757,7 @@ S_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
         if ( set_bit ) { /* bitmap only alloced when !(UTF&&Folding) */
             TRIE_BITMAP_SET(trie,*uc); /* store the raw first byte
                                           regardless of encoding */
-            if (OP( noper ) == EXACTFU_SS) {
+            if (OP( noper ) == EXACTFUP) {
                 /* false positives are ok, so just set this */
                 TRIE_BITMAP_SET(trie, LATIN_SMALL_LETTER_SHARP_S);
             }
@@ -2962,7 +2962,7 @@ S_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
                 && (    OP(noper) == flags
                     || (flags == EXACT && OP(noper) == EXACT_ONLY8)
                     || (flags == EXACTFU && (   OP(noper) == EXACTFU_ONLY8
-                                             || OP(noper) == EXACTFU_SS))) )
+                                             || OP(noper) == EXACTFUP))))
             {
                 const U8 *uc= (U8*)STRING(noper);
                 const U8 *e= uc + STR_LEN(noper);
@@ -3187,7 +3187,7 @@ S_make_trie(pTHX_ RExC_state_t *pRExC_state, regnode *startbranch,
                 && (    OP(noper) == flags
                     || (flags == EXACT && OP(noper) == EXACT_ONLY8)
                     || (flags == EXACTFU && (   OP(noper) == EXACTFU_ONLY8
-                                             || OP(noper) == EXACTFU_SS))) )
+                                             || OP(noper) == EXACTFUP))))
             {
                 const U8 *uc= (U8*)STRING(noper);
                 const U8 *e= uc + STR_LEN(noper);
@@ -3839,7 +3839,7 @@ S_construct_ahocorasick_from_trie(pTHX_ RExC_state_t *pRExC_state, regnode *sour
  * Both sides fold to "sss", but if the pattern is parsed to create a node that
  * would match just the \xDF, it won't be able to handle the case where a
  * successful match would have to cross the node's boundary.  The new approach
- * that hopefully generally solves the problem generates an EXACTFU_SS node
+ * that hopefully generally solves the problem generates an EXACTFUP node
  * that is "sss" in this case.
  *
  * It turns out that there are problems with all multi-character folds, and not
@@ -3855,28 +3855,46 @@ S_construct_ahocorasick_from_trie(pTHX_ RExC_state_t *pRExC_state, regnode *sour
  *      adjust the min length of the match, and the delta between min and max,
  *      so that the optimizer doesn't reject these possibilities based on size
  *      constraints.
- * 2)   For the sequence involving the Sharp s (\xDF), the node type EXACTFU_SS
- *      is used in non-UTF-8 patterns for an EXACTFU node that contains at
- *      least one "ss" sequence in it.  For UTF-8 patterns, the procedures in
- *      step 1) above are sufficient to handle these, but for non-UTF-8
- *      patterns and strings, this is the only case where there is a possible
- *      fold length change.  That means that a regular EXACTFU node without
- *      UTF-8 involvement doesn't have to concern itself with length changes,
- *      and so can be processed faster.  regexec.c takes advantage of this.
- *      Generally, an EXACTFish node that is in UTF-8 is pre-folded by
- *      regcomp.c (except EXACTFL, some of whose folds aren't known until
- *      runtime).  This saves effort in regex matching.  However, the
- *      pre-folding isn't done for non-UTF8 patterns because the fold of the
- *      MICRO SIGN requires UTF-8, and we don't want to slow things down by
- *      forcing the pattern into UTF8 unless necessary.  Also what EXACTF (and,
- *      again, EXACTFL) nodes fold to isn't known until runtime.  The fold
- *      possibilities for the non-UTF8 patterns are quite simple, except for
- *      the sharp s.  All the ones that don't involve a UTF-8 target string are
- *      members of a fold-pair, and arrays are set up for all of them so that
- *      the other member of the pair can be found quickly.  Code elsewhere in
- *      this file makes sure that in EXACTFU nodes, the sharp s gets folded to
- *      'ss', even if the pattern isn't UTF-8.  This avoids the issues
- *      described in the next item.
+ *
+ * 2)   For the sequence involving the LATIN SMALL LETTER SHARP S (U+00DF)
+ *      under /u, we fold it to 'ss' in regatom(), and in this routine, after
+ *      joining, we scan for occurrences of the sequence 'ss' in non-UTF-8
+ *      EXACTFU nodes.  The node type of such nodes is then changed to
+ *      EXACTFUP, indicating it is problematic, and needs careful handling.
+ *      (The procedures in step 1) above are sufficient to handle this case in
+ *      UTF-8 encoded nodes.)  The reason this is problematic is that this is
+ *      the only case where there is a possible fold length change in non-UTF-8
+ *      patterns.  By reserving a special node type for problematic cases, the
+ *      far more common regular EXACTFU nodes can be processed faster.
+ *      regexec.c takes advantage of this.
+ *
+ *      EXACTFUP has been created as a grab-bag for (hopefully uncommon)
+ *      problematic cases.   These all only occur when the pattern is not
+ *      UTF-8.  In addition to the 'ss' sequence where there is a possible fold
+ *      length change, it handles the situation where the string cannot be
+ *      entirely folded.  The strings in an EXACTFish node are folded as much
+ *      as possible during compilation in regcomp.c.  This saves effort in
+ *      regex matching.  By using an EXACTFUP node when it is not possible to
+ *      fully fold at compile time, regexec.c can know that everything in an
+ *      EXACTFU node is folded, so folding can be skipped at runtime.  The only
+ *      case where folding in EXACTFU nodes can't be done at compile time is
+ *      the presumably uncommon MICRO SIGN, when the pattern isn't UTF-8.  This
+ *      is because its fold requires UTF-8 to represent.  Thus EXACTFUP nodes
+ *      handle two very different cases.  Alternatively, there could have been
+ *      a node type where there are length changes, one for unfolded, and one
+ *      for both.  If yet another special case needed to be created, the number
+ *      of required node types would have to go to 7.  khw figures that even
+ *      though there are plenty of node types to spare, that the maintenance
+ *      cost wasn't worth the small speedup of doing it that way, especially
+ *      since he thinks the MICRO SIGN is rarely encountered in practice.
+ *
+ *      There are other cases where folding isn't done at compile time, but
+ *      none of them are under /u, and hence not for EXACTFU nodes.  The folds
+ *      in EXACTFL nodes aren't known until runtime, and vary as the locale
+ *      changes.  Some folds in EXACTF depend on if the runtime target string
+ *      is UTF-8 or not.  (regatom() will create an EXACTFU node even under /di
+ *      when no fold in it depends on the UTF-8ness of the target string.)
+ *
  * 3)   A problem remains for unfolded multi-char folds. (These occur when the
  *      validity of the fold won't be known until runtime, and so must remain
  *      unfolded for now.  This happens for the sharp s in EXACTF and EXACTFAA
@@ -4334,7 +4352,7 @@ S_join_exact(pTHX_ RExC_state_t *pRExC_state, regnode *scan,
                      * which we don't know until runtime.  EXACTFL nodes can't
                      * transform into EXACTFU nodes */
                     if (OP(scan) != EXACTF && OP(scan) != EXACTFL) {
-                        OP(scan) = EXACTFU_SS;
+                        OP(scan) = EXACTFUP;
                     }
                }
 
@@ -4801,7 +4819,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
                                 EXACT_ONLY8     | EXACT
                                 EXACTFU         | EXACTFU
                                 EXACTFU_ONLY8   | EXACTFU
-                                EXACTFU_SS      | EXACTFU
+                                EXACTFUP        | EXACTFU
                                 EXACTFAA        | EXACTFAA
                                 EXACTL          | EXACTL
                                 EXACTFLU8       | EXACTFLU8
@@ -4814,7 +4832,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
                          ? EXACT                                            \
                          : (     EXACTFU == (X)                             \
                               || EXACTFU_ONLY8 == (X)                       \
-                              || EXACTFU_SS == (X) )                        \
+                              || EXACTFUP == (X) )                          \
                            ? EXACTFU                                        \
                            : ( EXACTFAA == (X) )                            \
                              ? EXACTFAA                                     \
@@ -14710,6 +14728,11 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                     }
 
                     if (node_type == EXACTFU) {
+
+                        /* Because the MICRO SIGN folds to something
+                         * representable only in UTF-8, we use a special node
+                         * when we aren't in UTF-8, so can't represent that
+                         * fold */
                         if (UNLIKELY(has_micro_sign)) {
 
                             /* The micro sign is the only below 256 character
@@ -19497,7 +19520,7 @@ S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p,
                 case EXACTFU:
                 case EXACTFU_ONLY8:
                 case EXACTFLU8:
-                case EXACTFU_SS:
+                case EXACTFUP:
                 case EXACTFL:
                         if( exact == PSEUDO )
                             exact= OP(REGNODE_p(scan));
index bdbe059..8033a13 100644 (file)
@@ -107,7 +107,6 @@ EXACTFAA    EXACT,      str   ; Match this string using /iaa rules (w/len) (stri
 
 # End of important relative ordering.
 
-EXACTFU_SS  EXACT,      str      ; Match this string using /iu rules (w/len); (string not UTF-8, only portions guaranteed to be folded; folded length > unfolded).
 EXACTFUP    EXACT,      str      ; Match this string using /iu rules (w/len); (string not UTF-8, not guaranteed to be folded; and its Problematic).
 # In order for a non-UTF-8 EXACTFAA to think the pattern is pre-folded when
 # matching a UTF-8 target string, there would have to be something like an
index 63d4a94..43ce53d 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2320,7 +2320,6 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
         folder = foldEQ_locale;
         goto do_exactf_non_utf8;
 
-    case EXACTFU_SS:
     case EXACTFUP:      /* Problematic even though pattern isn't UTF-8.  Use
                            full functionality normally not done except for
                            UTF-8 */
@@ -4663,7 +4662,6 @@ S_setup_EXACTISH_ST_c1_c2(pTHX_ const regnode * const text_node, int *c1p,
                         assert(! is_utf8_pat);
                         /* FALLTHROUGH */
                     case EXACTFAA:
-                    case EXACTFU_SS:
                     case EXACTFUP:
                     case EXACTFU:
                         c2 = PL_fold_latin1[c1];
@@ -6422,7 +6420,6 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
            fold_utf8_flags = FOLDEQ_S2_ALREADY_FOLDED;
            goto do_exactf;
 
-       case EXACTFU_SS:         /*  /\x{df}/iu   */
         case EXACTFUP:          /*  /foo/iu, and something is problematic in
                                     'foo' so can't take shortcuts. */
             assert(! is_utf8_pat);
@@ -6465,7 +6462,6 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
 
            if (   utf8_target
                 || is_utf8_pat
-                || state_num == EXACTFU_SS
                 || state_num == EXACTFUP
                 || (state_num == EXACTFL && IN_UTF8_CTYPE_LOCALE))
             {
@@ -9367,7 +9363,6 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
         }
         /* FALLTHROUGH */
 
-    case EXACTFU_SS:
     case EXACTFUP:
 
       do_exactf: {
index 88609ed..da6a28c 100644 (file)
@@ -6,8 +6,8 @@
 
 /* Regops and State definitions */
 
-#define REGNODE_MAX            105
-#define REGMATCH_STATE_MAX     145
+#define REGNODE_MAX            104
+#define REGMATCH_STATE_MAX     144
 
 #define        END                     0       /* 0000 End of program. */
 #define        SUCCEED                 1       /* 0x01 Return from a subroutine, basically. */
 #define        EXACTFL                 39      /* 0x27 Match this string using /il rules (w/len); (string not guaranteed to be folded). */
 #define        EXACTFU                 40      /* 0x28 Match this string using /iu rules (w/len); (string folded iff in UTF-8; non-UTF8 folded length <= unfolded). */
 #define        EXACTFAA                41      /* 0x29 Match this string using /iaa rules (w/len) (string folded iff in UTF-8; non-UTF8 folded length <= unfolded). */
-#define        EXACTFU_SS              42      /* 0x2a Match this string using /iu rules (w/len); (string not UTF-8, only portions guaranteed to be folded; folded length > unfolded). */
-#define        EXACTFUP                43      /* 0x2b Match this string using /iu rules (w/len); (string not UTF-8, not guaranteed to be folded; and its Problematic). */
-#define        EXACTFLU8               44      /* 0x2c Like EXACTFU, but use /il, UTF-8, folded, and everything in it is above 255. */
-#define        EXACTFAA_NO_TRIE        45      /* 0x2d Match this string using /iaa rules (w/len) (string not UTF-8, not guaranteed to be folded, not currently trie-able). */
-#define        EXACT_ONLY8             46      /* 0x2e Like EXACT, but only UTF-8 encoded targets can match */
-#define        EXACTFU_ONLY8           47      /* 0x2f Like EXACTFU, but only UTF-8 encoded targets can match */
-#define        EXACTFS_B_U             48      /* 0x30 EXACTFU but begins with [Ss]; (string not UTF-8; compile-time only). */
-#define        EXACTFS_E_U             49      /* 0x31 EXACTFU but ends with [Ss]; (string not UTF-8; compile-time only). */
-#define        EXACTFS_BE_U            50      /* 0x32 EXACTFU but begins and ends with [Ss]; (string not UTF-8; compile-time only). */
-#define        NOTHING                 51      /* 0x33 Match empty string. */
-#define        TAIL                    52      /* 0x34 Match empty string. Can jump here from outside. */
-#define        STAR                    53      /* 0x35 Match this (simple) thing 0 or more times. */
-#define        PLUS                    54      /* 0x36 Match this (simple) thing 1 or more times. */
-#define        CURLY                   55      /* 0x37 Match this simple thing {n,m} times. */
-#define        CURLYN                  56      /* 0x38 Capture next-after-this simple thing */
-#define        CURLYM                  57      /* 0x39 Capture this medium-complex thing {n,m} times. */
-#define        CURLYX                  58      /* 0x3a Match this complex thing {n,m} times. */
-#define        WHILEM                  59      /* 0x3b Do curly processing and see if rest matches. */
-#define        OPEN                    60      /* 0x3c Mark this point in input as start of #n. */
-#define        CLOSE                   61      /* 0x3d Close corresponding OPEN of #n. */
-#define        SROPEN                  62      /* 0x3e Same as OPEN, but for script run */
-#define        SRCLOSE                 63      /* 0x3f Close preceding SROPEN */
-#define        REF                     64      /* 0x40 Match some already matched string */
-#define        REFF                    65      /* 0x41 Match already matched string, folded using native charset rules for non-utf8 */
-#define        REFFL                   66      /* 0x42 Match already matched string, folded in loc. */
-#define        REFFU                   67      /* 0x43 Match already matched string, folded using unicode rules for non-utf8 */
-#define        REFFA                   68      /* 0x44 Match already matched string, folded using unicode rules for non-utf8, no mixing ASCII, non-ASCII */
-#define        NREF                    69      /* 0x45 Match some already matched string */
-#define        NREFF                   70      /* 0x46 Match already matched string, folded using native charset rules for non-utf8 */
-#define        NREFFL                  71      /* 0x47 Match already matched string, folded in loc. */
-#define        NREFFU                  72      /* 0x48 Match already matched string, folded using unicode rules for non-utf8 */
-#define        NREFFA                  73      /* 0x49 Match already matched string, folded using unicode rules for non-utf8, no mixing ASCII, non-ASCII */
-#define        LONGJMP                 74      /* 0x4a Jump far away. */
-#define        BRANCHJ                 75      /* 0x4b BRANCH with long offset. */
-#define        IFMATCH                 76      /* 0x4c Succeeds if the following matches. */
-#define        UNLESSM                 77      /* 0x4d Fails if the following matches. */
-#define        SUSPEND                 78      /* 0x4e "Independent" sub-RE. */
-#define        IFTHEN                  79      /* 0x4f Switch, should be preceded by switcher. */
-#define        GROUPP                  80      /* 0x50 Whether the group matched. */
-#define        EVAL                    81      /* 0x51 Execute some Perl code. */
-#define        MINMOD                  82      /* 0x52 Next operator is not greedy. */
-#define        LOGICAL                 83      /* 0x53 Next opcode should set the flag only. */
-#define        RENUM                   84      /* 0x54 Group with independently numbered parens. */
-#define        TRIE                    85      /* 0x55 Match many EXACT(F[ALU]?)? at once. flags==type */
-#define        TRIEC                   86      /* 0x56 Same as TRIE, but with embedded charclass data */
-#define        AHOCORASICK             87      /* 0x57 Aho Corasick stclass. flags==type */
-#define        AHOCORASICKC            88      /* 0x58 Same as AHOCORASICK, but with embedded charclass data */
-#define        GOSUB                   89      /* 0x59 recurse to paren arg1 at (signed) ofs arg2 */
-#define        NGROUPP                 90      /* 0x5a Whether the group matched. */
-#define        INSUBP                  91      /* 0x5b Whether we are in a specific recurse. */
-#define        DEFINEP                 92      /* 0x5c Never execute directly. */
-#define        ENDLIKE                 93      /* 0x5d Used only for the type field of verbs */
-#define        OPFAIL                  94      /* 0x5e Same as (?!), but with verb arg */
-#define        ACCEPT                  95      /* 0x5f Accepts the current matched string, with verbar */
-#define        VERB                    96      /* 0x60 Used only for the type field of verbs */
-#define        PRUNE                   97      /* 0x61 Pattern fails at this startpoint if no-backtracking through this */
-#define        MARKPOINT               98      /* 0x62 Push the current location for rollback by cut. */
-#define        SKIP                    99      /* 0x63 On failure skip forward (to the mark) before retrying */
-#define        COMMIT                  100     /* 0x64 Pattern fails outright if backtracking through this */
-#define        CUTGROUP                101     /* 0x65 On failure go to the next alternation in the group */
-#define        KEEPS                   102     /* 0x66 $& begins here. */
-#define        LNBREAK                 103     /* 0x67 generic newline pattern */
-#define        OPTIMIZED               104     /* 0x68 Placeholder for dump. */
-#define        PSEUDO                  105     /* 0x69 Pseudo opcode for internal use. */
+#define        EXACTFUP                42      /* 0x2a Match this string using /iu rules (w/len); (string not UTF-8, not guaranteed to be folded; and its Problematic). */
+#define        EXACTFLU8               43      /* 0x2b Like EXACTFU, but use /il, UTF-8, folded, and everything in it is above 255. */
+#define        EXACTFAA_NO_TRIE        44      /* 0x2c Match this string using /iaa rules (w/len) (string not UTF-8, not guaranteed to be folded, not currently trie-able). */
+#define        EXACT_ONLY8             45      /* 0x2d Like EXACT, but only UTF-8 encoded targets can match */
+#define        EXACTFU_ONLY8           46      /* 0x2e Like EXACTFU, but only UTF-8 encoded targets can match */
+#define        EXACTFS_B_U             47      /* 0x2f EXACTFU but begins with [Ss]; (string not UTF-8; compile-time only). */
+#define        EXACTFS_E_U             48      /* 0x30 EXACTFU but ends with [Ss]; (string not UTF-8; compile-time only). */
+#define        EXACTFS_BE_U            49      /* 0x31 EXACTFU but begins and ends with [Ss]; (string not UTF-8; compile-time only). */
+#define        NOTHING                 50      /* 0x32 Match empty string. */
+#define        TAIL                    51      /* 0x33 Match empty string. Can jump here from outside. */
+#define        STAR                    52      /* 0x34 Match this (simple) thing 0 or more times. */
+#define        PLUS                    53      /* 0x35 Match this (simple) thing 1 or more times. */
+#define        CURLY                   54      /* 0x36 Match this simple thing {n,m} times. */
+#define        CURLYN                  55      /* 0x37 Capture next-after-this simple thing */
+#define        CURLYM                  56      /* 0x38 Capture this medium-complex thing {n,m} times. */
+#define        CURLYX                  57      /* 0x39 Match this complex thing {n,m} times. */
+#define        WHILEM                  58      /* 0x3a Do curly processing and see if rest matches. */
+#define        OPEN                    59      /* 0x3b Mark this point in input as start of #n. */
+#define        CLOSE                   60      /* 0x3c Close corresponding OPEN of #n. */
+#define        SROPEN                  61      /* 0x3d Same as OPEN, but for script run */
+#define        SRCLOSE                 62      /* 0x3e Close preceding SROPEN */
+#define        REF                     63      /* 0x3f Match some already matched string */
+#define        REFF                    64      /* 0x40 Match already matched string, folded using native charset rules for non-utf8 */
+#define        REFFL                   65      /* 0x41 Match already matched string, folded in loc. */
+#define        REFFU                   66      /* 0x42 Match already matched string, folded using unicode rules for non-utf8 */
+#define        REFFA                   67      /* 0x43 Match already matched string, folded using unicode rules for non-utf8, no mixing ASCII, non-ASCII */
+#define        NREF                    68      /* 0x44 Match some already matched string */
+#define        NREFF                   69      /* 0x45 Match already matched string, folded using native charset rules for non-utf8 */
+#define        NREFFL                  70      /* 0x46 Match already matched string, folded in loc. */
+#define        NREFFU                  71      /* 0x47 Match already matched string, folded using unicode rules for non-utf8 */
+#define        NREFFA                  72      /* 0x48 Match already matched string, folded using unicode rules for non-utf8, no mixing ASCII, non-ASCII */
+#define        LONGJMP                 73      /* 0x49 Jump far away. */
+#define        BRANCHJ                 74      /* 0x4a BRANCH with long offset. */
+#define        IFMATCH                 75      /* 0x4b Succeeds if the following matches. */
+#define        UNLESSM                 76      /* 0x4c Fails if the following matches. */
+#define        SUSPEND                 77      /* 0x4d "Independent" sub-RE. */
+#define        IFTHEN                  78      /* 0x4e Switch, should be preceded by switcher. */
+#define        GROUPP                  79      /* 0x4f Whether the group matched. */
+#define        EVAL                    80      /* 0x50 Execute some Perl code. */
+#define        MINMOD                  81      /* 0x51 Next operator is not greedy. */
+#define        LOGICAL                 82      /* 0x52 Next opcode should set the flag only. */
+#define        RENUM                   83      /* 0x53 Group with independently numbered parens. */
+#define        TRIE                    84      /* 0x54 Match many EXACT(F[ALU]?)? at once. flags==type */
+#define        TRIEC                   85      /* 0x55 Same as TRIE, but with embedded charclass data */
+#define        AHOCORASICK             86      /* 0x56 Aho Corasick stclass. flags==type */
+#define        AHOCORASICKC            87      /* 0x57 Same as AHOCORASICK, but with embedded charclass data */
+#define        GOSUB                   88      /* 0x58 recurse to paren arg1 at (signed) ofs arg2 */
+#define        NGROUPP                 89      /* 0x59 Whether the group matched. */
+#define        INSUBP                  90      /* 0x5a Whether we are in a specific recurse. */
+#define        DEFINEP                 91      /* 0x5b Never execute directly. */
+#define        ENDLIKE                 92      /* 0x5c Used only for the type field of verbs */
+#define        OPFAIL                  93      /* 0x5d Same as (?!), but with verb arg */
+#define        ACCEPT                  94      /* 0x5e Accepts the current matched string, with verbar */
+#define        VERB                    95      /* 0x5f Used only for the type field of verbs */
+#define        PRUNE                   96      /* 0x60 Pattern fails at this startpoint if no-backtracking through this */
+#define        MARKPOINT               97      /* 0x61 Push the current location for rollback by cut. */
+#define        SKIP                    98      /* 0x62 On failure skip forward (to the mark) before retrying */
+#define        COMMIT                  99      /* 0x63 Pattern fails outright if backtracking through this */
+#define        CUTGROUP                100     /* 0x64 On failure go to the next alternation in the group */
+#define        KEEPS                   101     /* 0x65 $& begins here. */
+#define        LNBREAK                 102     /* 0x66 generic newline pattern */
+#define        OPTIMIZED               103     /* 0x67 Placeholder for dump. */
+#define        PSEUDO                  104     /* 0x68 Pseudo opcode for internal use. */
        /* ------------ States ------------- */
 #define        TRIE_next               (REGNODE_MAX + 1)       /* state for TRIE */
 #define        TRIE_next_fail          (REGNODE_MAX + 2)       /* state for TRIE */
@@ -207,7 +206,6 @@ EXTCONST U8 PL_regkind[] = {
        EXACT,          /* EXACTFL                */
        EXACT,          /* EXACTFU                */
        EXACT,          /* EXACTFAA               */
-       EXACT,          /* EXACTFU_SS             */
        EXACT,          /* EXACTFUP               */
        EXACT,          /* EXACTFLU8              */
        EXACT,          /* EXACTFAA_NO_TRIE       */
@@ -362,7 +360,6 @@ static const U8 regarglen[] = {
        0,                                      /* EXACTFL      */
        0,                                      /* EXACTFU      */
        0,                                      /* EXACTFAA     */
-       0,                                      /* EXACTFU_SS   */
        0,                                      /* EXACTFUP     */
        0,                                      /* EXACTFLU8    */
        0,                                      /* EXACTFAA_NO_TRIE */
@@ -473,7 +470,6 @@ static const char reg_off_by_arg[] = {
        0,      /* EXACTFL      */
        0,      /* EXACTFU      */
        0,      /* EXACTFAA     */
-       0,      /* EXACTFU_SS   */
        0,      /* EXACTFUP     */
        0,      /* EXACTFLU8    */
        0,      /* EXACTFAA_NO_TRIE */
@@ -590,70 +586,69 @@ EXTCONST char * const PL_reg_name[] = {
        "EXACTFL",                      /* 0x27 */
        "EXACTFU",                      /* 0x28 */
        "EXACTFAA",                     /* 0x29 */
-       "EXACTFU_SS",                   /* 0x2a */
-       "EXACTFUP",                     /* 0x2b */
-       "EXACTFLU8",                    /* 0x2c */
-       "EXACTFAA_NO_TRIE",             /* 0x2d */
-       "EXACT_ONLY8",                  /* 0x2e */
-       "EXACTFU_ONLY8",                /* 0x2f */
-       "EXACTFS_B_U",                  /* 0x30 */
-       "EXACTFS_E_U",                  /* 0x31 */
-       "EXACTFS_BE_U",                 /* 0x32 */
-       "NOTHING",                      /* 0x33 */
-       "TAIL",                         /* 0x34 */
-       "STAR",                         /* 0x35 */
-       "PLUS",                         /* 0x36 */
-       "CURLY",                        /* 0x37 */
-       "CURLYN",                       /* 0x38 */
-       "CURLYM",                       /* 0x39 */
-       "CURLYX",                       /* 0x3a */
-       "WHILEM",                       /* 0x3b */
-       "OPEN",                         /* 0x3c */
-       "CLOSE",                        /* 0x3d */
-       "SROPEN",                       /* 0x3e */
-       "SRCLOSE",                      /* 0x3f */
-       "REF",                          /* 0x40 */
-       "REFF",                         /* 0x41 */
-       "REFFL",                        /* 0x42 */
-       "REFFU",                        /* 0x43 */
-       "REFFA",                        /* 0x44 */
-       "NREF",                         /* 0x45 */
-       "NREFF",                        /* 0x46 */
-       "NREFFL",                       /* 0x47 */
-       "NREFFU",                       /* 0x48 */
-       "NREFFA",                       /* 0x49 */
-       "LONGJMP",                      /* 0x4a */
-       "BRANCHJ",                      /* 0x4b */
-       "IFMATCH",                      /* 0x4c */
-       "UNLESSM",                      /* 0x4d */
-       "SUSPEND",                      /* 0x4e */
-       "IFTHEN",                       /* 0x4f */
-       "GROUPP",                       /* 0x50 */
-       "EVAL",                         /* 0x51 */
-       "MINMOD",                       /* 0x52 */
-       "LOGICAL",                      /* 0x53 */
-       "RENUM",                        /* 0x54 */
-       "TRIE",                         /* 0x55 */
-       "TRIEC",                        /* 0x56 */
-       "AHOCORASICK",                  /* 0x57 */
-       "AHOCORASICKC",                 /* 0x58 */
-       "GOSUB",                        /* 0x59 */
-       "NGROUPP",                      /* 0x5a */
-       "INSUBP",                       /* 0x5b */
-       "DEFINEP",                      /* 0x5c */
-       "ENDLIKE",                      /* 0x5d */
-       "OPFAIL",                       /* 0x5e */
-       "ACCEPT",                       /* 0x5f */
-       "VERB",                         /* 0x60 */
-       "PRUNE",                        /* 0x61 */
-       "MARKPOINT",                    /* 0x62 */
-       "SKIP",                         /* 0x63 */
-       "COMMIT",                       /* 0x64 */
-       "CUTGROUP",                     /* 0x65 */
-       "KEEPS",                        /* 0x66 */
-       "LNBREAK",                      /* 0x67 */
-       "OPTIMIZED",                    /* 0x68 */
-       "PSEUDO",                       /* 0x69 */
+       "EXACTFUP",                     /* 0x2a */
+       "EXACTFLU8",                    /* 0x2b */
+       "EXACTFAA_NO_TRIE",             /* 0x2c */
+       "EXACT_ONLY8",                  /* 0x2d */
+       "EXACTFU_ONLY8",                /* 0x2e */
+       "EXACTFS_B_U",                  /* 0x2f */
+       "EXACTFS_E_U",                  /* 0x30 */
+       "EXACTFS_BE_U",                 /* 0x31 */
+       "NOTHING",                      /* 0x32 */
+       "TAIL",                         /* 0x33 */
+       "STAR",                         /* 0x34 */
+       "PLUS",                         /* 0x35 */
+       "CURLY",                        /* 0x36 */
+       "CURLYN",                       /* 0x37 */
+       "CURLYM",                       /* 0x38 */
+       "CURLYX",                       /* 0x39 */
+       "WHILEM",                       /* 0x3a */
+       "OPEN",                         /* 0x3b */
+       "CLOSE",                        /* 0x3c */
+       "SROPEN",                       /* 0x3d */
+       "SRCLOSE",                      /* 0x3e */
+       "REF",                          /* 0x3f */
+       "REFF",                         /* 0x40 */
+       "REFFL",                        /* 0x41 */
+       "REFFU",                        /* 0x42 */
+       "REFFA",                        /* 0x43 */
+       "NREF",                         /* 0x44 */
+       "NREFF",                        /* 0x45 */
+       "NREFFL",                       /* 0x46 */
+       "NREFFU",                       /* 0x47 */
+       "NREFFA",                       /* 0x48 */
+       "LONGJMP",                      /* 0x49 */
+       "BRANCHJ",                      /* 0x4a */
+       "IFMATCH",                      /* 0x4b */
+       "UNLESSM",                      /* 0x4c */
+       "SUSPEND",                      /* 0x4d */
+       "IFTHEN",                       /* 0x4e */
+       "GROUPP",                       /* 0x4f */
+       "EVAL",                         /* 0x50 */
+       "MINMOD",                       /* 0x51 */
+       "LOGICAL",                      /* 0x52 */
+       "RENUM",                        /* 0x53 */
+       "TRIE",                         /* 0x54 */
+       "TRIEC",                        /* 0x55 */
+       "AHOCORASICK",                  /* 0x56 */
+       "AHOCORASICKC",                 /* 0x57 */
+       "GOSUB",                        /* 0x58 */
+       "NGROUPP",                      /* 0x59 */
+       "INSUBP",                       /* 0x5a */
+       "DEFINEP",                      /* 0x5b */
+       "ENDLIKE",                      /* 0x5c */
+       "OPFAIL",                       /* 0x5d */
+       "ACCEPT",                       /* 0x5e */
+       "VERB",                         /* 0x5f */
+       "PRUNE",                        /* 0x60 */
+       "MARKPOINT",                    /* 0x61 */
+       "SKIP",                         /* 0x62 */
+       "COMMIT",                       /* 0x63 */
+       "CUTGROUP",                     /* 0x64 */
+       "KEEPS",                        /* 0x65 */
+       "LNBREAK",                      /* 0x66 */
+       "OPTIMIZED",                    /* 0x67 */
+       "PSEUDO",                       /* 0x68 */
        /* ------------ States ------------- */
        "TRIE_next",                    /* REGNODE_MAX +0x01 */
        "TRIE_next_fail",               /* REGNODE_MAX +0x02 */
@@ -788,7 +783,7 @@ EXTCONST U8 PL_varies[] __attribute__deprecated__ = {
 EXTCONST U8 PL_varies_bitmask[];
 #else
 EXTCONST U8 PL_varies_bitmask[] = {
-    0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xE0, 0x0F, 0xFF, 0xCB, 0x00, 0x00, 0x00, 0x00
+    0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0xF0, 0x87, 0xFF, 0x65, 0x00, 0x00, 0x00, 0x00
 };
 #endif /* DOINIT */