Test for null or undefined with one tag compare on arm64 and x64
Categories
(Core :: JavaScript Engine: JIT, task, P2)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox161 | --- | fixed |
People
(Reporter: andrew, Assigned: andrew)
References
Details
Attachments
(1 external file)
The JITs test whether a Value is null or undefined at a dozen sites (loose equality with null, the Coalesce and IsNullOrUndefined ops, CheckObjCoercible, the guards for optional chains and the truthiness tests) as two tag compares with two branches.
Null and undefined differ in a single tag bit and the other two type codes with the same upper bits are unused, so one comparison of the bits of the Value above that bit tells whether it is either of them. A branchTestNullOrUndefined helper in MacroAssembler can do this at those sites: on arm64 and x64 the ValueOperand form shifts the Value and compares once, and where a tag has already been extracted for further tests the arm64 Register form uses ccmn to keep a single branch. The other backends keep the two compares.
The test of a Coalesce operand in Ion on arm64
asr x16, x0, #47
cmn w16, #12
b.eq nullOrUndefined
cmn w16, #10
b.eq nullOrUndefined
becomes
asr x16, x0, #49
cmn w16, #3
b.eq nullOrUndefined
and on x64
movq %rax, %r11
shrq $47, %r11
cmpl $0x1fff4, %r11d
je nullOrUndefined
cmpl $0x1fff6, %r11d
je nullOrUndefined
becomes
movq %rax, %r11
shrq $49, %r11
cmpl $0x7ffd, %r11d
je nullOrUndefined
In the code compiled during a JetStream 3 run on arm64, the ValueOperand form replaces the pair of tests at 5,501 Ion and 2,157 Baseline sites, two instructions fewer each with one of them a branch, and the ccmn form at 10,462 Ion and 26 Baseline sites, a branch fewer each. Value.h documents the layout constraint and asserts it. Found with armlint.
| Assignee | ||
Comment 1•18 days ago
|
||
Null and undefined differ in a single tag bit and the other two type codes
with the same upper bits are unused, so one comparison of the Value's bits
above that one tells whether it is either of them. The JITs test the pair
at a dozen sites (loose equality with null, the Coalesce and
IsNullOrUndefined ops, CheckObjCoercible, the guards for optional chains
and the truthiness tests) as two tag compares with two branches.
This adds branchTestNullOrUndefined to the MacroAssembler and uses it at
those sites. The ValueOperand form shifts the Value and compares once on
arm64 and x64; the Register form, for callers that have extracted the tag
for further tests, uses ccmn on arm64 to keep a single branch. The other
backends emit the two compares as before.
The test of the Coalesce operand in Ion was, on arm64,
asr x16, x0, #47
cmn w16, #12
b.eq nullOrUndefined
cmn w16, #10
b.eq nullOrUndefined
and becomes
asr x16, x0, #49
cmn w16, #3
b.eq nullOrUndefined
and on x64 it was
movq %rax, %r11
shrq $47, %r11
cmpl $0x1fff4, %r11d
je nullOrUndefined
cmpl $0x1fff6, %r11d
je nullOrUndefined
and becomes
movq %rax, %r11
shrq $49, %r11
cmpl $0x7ffd, %r11d
je nullOrUndefined
The CacheIR stub for loose equality with null goes on to test for an
object, so it keeps the extracted tag; on arm64 it was
asr x16, x0, #47
cmn w16, #12
b.eq equal
cmn w16, #10
b.eq equal
cmn w16, #4
b.ne notEqual
and becomes
asr x16, x0, #47
cmn w16, #12
ccmn w16, #10, #4, ne
b.eq equal
cmn w16, #4
b.ne notEqual
while x64 keeps the two compares there.
In the code compiled during a JetStream 3 run on arm64, the ValueOperand
form replaces the pair of tests at 5,501 Ion and 2,157 Baseline sites, two
instructions fewer each with one of them a branch, and the ccmn form at
10,462 Ion and 26 Baseline sites, a branch fewer each. Ion still tests null
and then undefined at 2,491 sites, all in loadAtomOrSymbolAndHash, which
maps the two to different atoms.
Value.h documents the layout constraint and asserts it.
Found with armlint.
Updated•18 days ago
|
Updated•18 days ago
|
Comment 4•17 days ago
|
||
Revert for causing lint failures on MacroAssembler.h.
Comment 6•17 days ago
|
||
| bugherder | ||
| Assignee | ||
Updated•15 days ago
|
Updated•6 days ago
|
Description
•