Closed Bug 1734405 Opened 2 months ago Closed 2 months ago

Compare small constant strings using inline assembly

Categories

(Core :: JavaScript Engine: JIT, enhancement)

enhancement

Tracking

()

RESOLVED FIXED
95 Branch
Tracking Status
firefox95 --- fixed

People

(Reporter: anba, Assigned: anba)

References

(Blocks 1 open bug)

Details

Attachments

(4 files)

The current string comparison code is always using a VM-call to determine if two strings are equal to each other (after pointer, atom, and length checks), cf. MacroAssembler::compareStrings(). We should improve the case when one operand is a compile-time constant string, similar to how Clang and GCC are optimising:

bool test(const char* s) {
    return memcmp(s, "spidermonkey", 12);
}

This optimisation helps to remove a few million VM-calls in benchmarks (Speedometer2, JetStream2, ARES6) and it also applies to real-world code, for example when scrolling down on https://www.twitch.tv/directory, whenever data is reloaded, 20K VM-calls are performed alone for string comparisons.

This bug is different from bug 1326193 insofar that only small constant strings will be optimised.

Nice, I've definitely seen this show up when looking at VM call counts (bug 1730863).

Blocks: 1730863

This optimises str == "" comparison which are now rewritten to str.length == 0.

The change results in less generated code and is also slightly faster.

Add cmp{8,16,64}() in preparation for a later patch in this stack.

Depends on D127665

Add branch{8,16}() in preparation for a later patch in this stack.

Depends on D127666

Add an optimisation to compare small constant strings using inline assembly code.
For example x == "spidermonkey" is now optimised to:

; rcx: string
; rax: output

; Compare the first eight characters "spidermo".
; 0x73 = s, 0x70 = p, etc.
    cmovzq 0x08(%rcx), %rax
    mov $0x6F6D726564697073, %r11
    cmpq %r11, (%rax)
    jnz <not-equal>

; Compare the next four characters "nkey".
    cmpl $0x79656B6E, 0x08(%rax)
    jnz <not-equal>

; Return true when both strings are equal.
    mov $0x01, %eax
    jmp <done>

; Return false when the strings aren't equal.
not-equal:
    xor %eax, %eax

done:

The current maximum for inline string comparison is 32 Latin-1 characters. This
number was chosen because it's a multiple of eight and covers most constant
strings observed while randomly browsing around. This maximum means we generate
at most four comparison instructions on 64-bit systems.

Depends on D127667

Pushed by andre.bargull@gmail.com:
https://hg.mozilla.org/integration/autoland/rev/a6aebcfcdc67
Part 1: Fold comparison with empty string. r=jandem
https://hg.mozilla.org/integration/autoland/rev/f3a3a2b4de50
Part 2: Add MacroAssembler::cmp{8,16,64}Set(). r=jandem
https://hg.mozilla.org/integration/autoland/rev/fac49dce2402
Part 3: Add MacroAssembler::branch{8,16}(). r=jandem
https://hg.mozilla.org/integration/autoland/rev/14f5245a7859
Part 4: Compare small constant strings using inline assembly. r=jandem
Regressions: 1735146
You need to log in before you can comment on or make changes to this bug.