Skip to content

Commit 8574350

Browse files
committed
regexp: speed up onepass prefix check
Remove an unnecessary check that the first operation matches - we know from compile-time that it is EmptyBeginText which will always match at position 0. This enables the call to i.hasPrefix to be done before unpacking the instruction or the first two runes. If the prefix does not match we go straight to return, and if it does match we need the runes after the match, so in either case unpacking the runes was unnecessary.
1 parent e1c294a commit 8574350

File tree

1 file changed

+22
-23
lines changed

1 file changed

+22
-23
lines changed

src/regexp/exec.go

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -401,45 +401,44 @@ func (re *Regexp) doOnePass(ir io.RuneReader, ib []byte, is string, pos, ncap in
401401
}
402402

403403
m := newOnePassMachine()
404+
matched := false
405+
i, _ := m.inputs.init(ir, ib, is)
406+
407+
r, r1 := endOfText, endOfText
408+
width, width1 := 0, 0
409+
var flag lazyFlag
410+
var pc int
411+
var inst onePassInst
412+
413+
// If there is a simple literal prefix, skip over it.
414+
if pos == 0 && len(re.prefix) > 0 && i.canCheckPrefix() {
415+
// Match requires literal prefix; fast search for it.
416+
if !i.hasPrefix(re) {
417+
goto Return
418+
}
419+
pos += len(re.prefix)
420+
pc = int(re.prefixEnd)
421+
} else {
422+
pc = re.onepass.Start
423+
}
424+
404425
if cap(m.matchcap) < ncap {
405426
m.matchcap = make([]int, ncap)
406427
} else {
407428
m.matchcap = m.matchcap[:ncap]
408429
}
409-
410-
matched := false
411430
for i := range m.matchcap {
412431
m.matchcap[i] = -1
413432
}
414433

415-
i, _ := m.inputs.init(ir, ib, is)
416-
417-
r, r1 := endOfText, endOfText
418-
width, width1 := 0, 0
419434
r, width = i.step(pos)
420-
if r != endOfText {
421-
r1, width1 = i.step(pos + width)
422-
}
423-
var flag lazyFlag
424435
if pos == 0 {
425436
flag = newLazyFlag(-1, r)
426437
} else {
427438
flag = i.context(pos)
428439
}
429-
pc := re.onepass.Start
430-
inst := re.onepass.Inst[pc]
431-
// If there is a simple literal prefix, skip over it.
432-
if pos == 0 && flag.match(syntax.EmptyOp(inst.Arg)) &&
433-
len(re.prefix) > 0 && i.canCheckPrefix() {
434-
// Match requires literal prefix; fast search for it.
435-
if !i.hasPrefix(re) {
436-
goto Return
437-
}
438-
pos += len(re.prefix)
439-
r, width = i.step(pos)
440+
if r != endOfText {
440441
r1, width1 = i.step(pos + width)
441-
flag = i.context(pos)
442-
pc = int(re.prefixEnd)
443442
}
444443
for {
445444
inst = re.onepass.Inst[pc]

0 commit comments

Comments
 (0)