Closed Bug 2086499 Opened 18 days ago Closed 17 days ago

Test for null or undefined with one tag compare on arm64 and x64

Categories

(Core :: JavaScript Engine: JIT, task, P2)

task

Tracking

()

RESOLVED FIXED
161 Branch
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.

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.

Assignee: nobody → andrew
Status: NEW → ASSIGNED
Severity: -- → N/A
Priority: -- → P2
Pushed by iireland@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/1a642409a20f https://hg.mozilla.org/integration/autoland/rev/0624f5aa4d79 Add branchTestNullOrUndefined and test both tags at once on arm64 and x64. r=iain
Pushed by imoraru@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/6e830f7e77b1 https://hg.mozilla.org/integration/autoland/rev/e65dee01f60d Revert "Bug 2086499 - Add branchTestNullOrUndefined and test both tags at once on arm64 and x64. r=iain" for causing lint failures on MacroAssembler.h.

Revert for causing lint failures on MacroAssembler.h.

Flags: needinfo?(andrew)
Pushed by iireland@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/37f6aa6605c5 https://hg.mozilla.org/integration/autoland/rev/f5e125ec7cca Add branchTestNullOrUndefined and test both tags at once on arm64 and x64. r=iain
Status: ASSIGNED → RESOLVED
Closed: 17 days ago
Resolution: --- → FIXED
Target Milestone: --- → 161 Branch
Blocks: 2087434
Blocks: 2087445
Flags: needinfo?(andrew)
QA Whiteboard: [qa-triage-done-c162/b161]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: