diff options
| author | Stefan Monnier | 2023-02-20 21:22:41 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2023-02-20 21:22:41 -0500 |
| commit | 5a864f23eb8a36ef435136c5b41cb01b875df399 (patch) | |
| tree | cc7b6d2ebd44f079f0f1a2ce99783a72bcba0eaf /src | |
| parent | e83c78b8c7784254c2c6f043530ab325c2fa7f16 (diff) | |
| download | emacs-5a864f23eb8a36ef435136c5b41cb01b875df399.tar.gz emacs-5a864f23eb8a36ef435136c5b41cb01b875df399.zip | |
regex-emacs.c: Reduce the use of backtracking a bit further
bug#61514 exhibited some undesirable backtracking in a case where
it's easy to avoid it by making `mutually_exclusive_p` just a bit
more careful.
* src/regex-emacs.c (mutually_exclusive_p): Handle `on_failure_jump`s.
* test/src/regex-emacs-tests.el (regexp-tests-backtrack-optimization):
Add a few tests.
Diffstat (limited to 'src')
| -rw-r--r-- | src/regex-emacs.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 2dca0d16ad9..2571812cb39 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c | |||
| @@ -3653,6 +3653,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1, | |||
| 3653 | re_opcode_t op2; | 3653 | re_opcode_t op2; |
| 3654 | bool multibyte = RE_MULTIBYTE_P (bufp); | 3654 | bool multibyte = RE_MULTIBYTE_P (bufp); |
| 3655 | unsigned char *pend = bufp->buffer + bufp->used; | 3655 | unsigned char *pend = bufp->buffer + bufp->used; |
| 3656 | re_char *p2_orig = p2; | ||
| 3656 | 3657 | ||
| 3657 | eassert (p1 >= bufp->buffer && p1 < pend | 3658 | eassert (p1 >= bufp->buffer && p1 < pend |
| 3658 | && p2 >= bufp->buffer && p2 <= pend); | 3659 | && p2 >= bufp->buffer && p2 <= pend); |
| @@ -3822,6 +3823,23 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1, | |||
| 3822 | case notcategoryspec: | 3823 | case notcategoryspec: |
| 3823 | return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]); | 3824 | return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]); |
| 3824 | 3825 | ||
| 3826 | case on_failure_jump_nastyloop: | ||
| 3827 | case on_failure_jump_smart: | ||
| 3828 | case on_failure_jump_loop: | ||
| 3829 | case on_failure_keep_string_jump: | ||
| 3830 | case on_failure_jump: | ||
| 3831 | { | ||
| 3832 | int mcnt; | ||
| 3833 | p2++; | ||
| 3834 | EXTRACT_NUMBER_AND_INCR (mcnt, p2); | ||
| 3835 | /* Don't just test `mcnt > 0` because non-greedy loops have | ||
| 3836 | their test at the end with an unconditional jump at the start. */ | ||
| 3837 | if (p2 + mcnt > p2_orig) /* Ensure forward progress. */ | ||
| 3838 | return (mutually_exclusive_p (bufp, p1, p2) | ||
| 3839 | && mutually_exclusive_p (bufp, p1, p2 + mcnt)); | ||
| 3840 | break; | ||
| 3841 | } | ||
| 3842 | |||
| 3825 | default: | 3843 | default: |
| 3826 | ; | 3844 | ; |
| 3827 | } | 3845 | } |