Commit ff89f89
committed
Only clear $~ once when #match "fails"
```
$ ips --ruby ruby-dev --ruby ruby-master -e '"".match?(/a/)' -e '"".match(/a/)'
ruby 4.1.0dev (2026-07-28T19:56:48Z master 120c8fa) +PRISM [arm64-darwin25]
"".match?(/a/): 40.578M i/s (± 1.4%)
"".match(/a/): 23.439M i/s (± 1.7%)
ruby 4.1.0dev (2026-07-28T19:56:48Z master 120c8fa) +PRISM [arm64-darwin25]
"".match?(/a/): 40.357M i/s (± 1.7%)
"".match(/a/): 20.285M i/s (± 1.5%)
Summary
"".match?(/a/) (ruby ruby-dev) ran
1.01 ± 0.02 times faster than "".match?(/a/) (ruby ruby-master)
1.73 ± 0.04 times faster than "".match(/a/) (ruby ruby-dev)
2.00 ± 0.04 times faster than "".match(/a/) (ruby ruby-master)
```
Previously, `reg_match_pos` cleared `$~` in every case where it returned
a negative offset except one: when a negative `pos` argument underflows
the start of the string. `rb_reg_match_m` had to account for this by
clearing `$~` for _any_ negative return, so every failed `Regexp#match`
(and `String#match`) which doesn't underflow ended up calling
`rb_backref_set` twice.
This commit moves the clear into the branch that was missing it, so
`reg_match_pos` maintains `$~` on all of its negative returns and its
callers no longer have to.1 parent 120c8fa commit ff89f89
1 file changed
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3830 | 3830 | | |
3831 | 3831 | | |
3832 | 3832 | | |
| 3833 | + | |
3833 | 3834 | | |
3834 | 3835 | | |
3835 | 3836 | | |
| |||
4024 | 4025 | | |
4025 | 4026 | | |
4026 | 4027 | | |
4027 | | - | |
4028 | 4028 | | |
4029 | 4029 | | |
4030 | 4030 | | |
| |||
0 commit comments