Compare small constant strings using inline assembly
Categories
(Core :: JavaScript Engine: JIT, enhancement)
Tracking
()
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.
Comment 1•3 years ago
|
||
Nice, I've definitely seen this show up when looking at VM call counts (bug 1730863).
Assignee | ||
Comment 2•3 years ago
|
||
This optimises str == ""
comparison which are now rewritten to str.length == 0
.
The change results in less generated code and is also slightly faster.
Assignee | ||
Comment 3•3 years ago
|
||
Add cmp{8,16,64}()
in preparation for a later patch in this stack.
Depends on D127665
Assignee | ||
Comment 4•3 years ago
|
||
Add branch{8,16}()
in preparation for a later patch in this stack.
Depends on D127666
Assignee | ||
Comment 5•3 years ago
|
||
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
Comment 7•3 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/a6aebcfcdc67
https://hg.mozilla.org/mozilla-central/rev/f3a3a2b4de50
https://hg.mozilla.org/mozilla-central/rev/fac49dce2402
https://hg.mozilla.org/mozilla-central/rev/14f5245a7859
Description
•