Fix and improve Atomic operations on riscv64
Categories
(Core :: JavaScript Engine: JIT, enhancement)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox155 | --- | fixed |
People
(Reporter: anba, Assigned: anba)
References
(Blocks 1 open bug)
Details
Attachments
(13 external files)
Improvements:
- Use AMO instructions instead of LR/SC loops where possible, because it needs fewer instructions and matches what Clang/GCC/V8 is using.
- Using AMO instructions also means we don't need to worry about constraining LR/SC loops (see below).
Fixes:
- Ensure LR/SC loops are always constrained, because unconstrained loops are allowed to never succeed.
- Wasm Atomic operations are missing index zero-extension
- Wasm compare-exchange in baseline doesn't sign-extend the expected value.
| Assignee | ||
Comment 1•3 months ago
|
||
These were probably needed at some point to explicitly cast from
ScratchRegisterScope to Register, but are now no longer necessary.
| Assignee | ||
Comment 2•3 months ago
|
||
Add zext_b and its companion method ZeroExtendByte. Then replace existing
callers to use either zext_b or ZeroExtendByte, depending on the surrounding
code.
Drive-by change:
- Remove
xlenuses inSignExtendByte, because we only support RV64.
| Assignee | ||
Comment 3•3 months ago
|
||
Add ZeroExtendShort which emits zext.h if the Zbb extension is available.
Drive-by change:
- Remove
xlenuses inSignExtendByte, because we only support RV64.
| Assignee | ||
Comment 4•3 months ago
|
||
Remove the old Simulator::amo() method because it didn't perform any
synchronization. Add AtomicMemoryHelper similar to upstream V8, but
only support SeqCst (Release+Acquire) ordering, so we can reuse the
atomic primitives from AtomicOperations.
Remove support for AMO min/max instructions, because there are no matching
primitives from AtomicOperations.
| Assignee | ||
Comment 5•3 months ago
|
||
Use AMO instructions amoswap.w/d if possible, otherwise fallback to the
existing LR/SC loop. Within the LR/SC loop ensure all requirements for
"constrained LR/SC loop" are fulfilled.
The "A" extension consists of the Zalrsc and Zaamo extensions, and the RV64G
base ISA requires support for the "A" extension, so it's always okay to emit
AMO instructions. This also matches Clang/GCC when using SeqCst std::atomic
operations and what V8 is using.
Adds new helpers Atomic{Offset,Mask,ShiftToOffset,ExtendResult} which are
reused in the next parts to avoid duplicating the same code multiple times.
| Assignee | ||
Comment 6•3 months ago
|
||
64-bit Atomic fetch operations can be implemented using a single AMO
instructions. The additional temp register is no longer needed.
| Assignee | ||
Comment 7•3 months ago
|
||
Use different implementation strategies based on the bit-width and operation:
- 32-bit operations can always use AMO instructions.
- 8/16-bit bitwise operations can be be implemented using 32-bit AMO instructions.
- For Add/Sub we need to keep using a LR/SC loop.
Merges AtomicFetchOp and AtomicEffectOp into a single AtomicFetchOrEffectOp
function to reduce code duplication. "Effect" operations pass zero_reg as the
output register.
| Assignee | ||
Comment 8•3 months ago
|
||
Change the implementation to follow "constrained LR/SC loop" constraints and
improve it to generate fewer instructions (based on what Clang is using for
C++ std::atomic operations).
| Assignee | ||
Comment 9•3 months ago
|
||
When AMO instructions are used, no input register is read after writing to the
output register, so we can use at-start allocations here.
Drive-by changes:
- Remove
constfor values to match other code.constalso doesn't give any
benefits, because the methods are short enough so it's easy to see that no
modifications take place. - Use more
auto*.
| Assignee | ||
Comment 10•3 months ago
|
||
After parts 2-3, xlen is now only used by the simulator.
| Assignee | ||
Comment 11•3 months ago
|
||
The Zba extension instructions add.uw and sh{1,2,3}add.uw are exactly what's
needed for Wasm load/store instructions with an Int32 index.
This patch adds enum ZeroExtendIndex to control when the index member of
BaseIndex needs to be zero-extended. "CodeGenerator-riscv64.cpp" and
"WasmBCMemory.cpp" now pass ZeroExtendIndex to the wasm load/store methods
instead of manually zero-extending the index.
This approach ensures better code generation and is also needed for part 13 to
add missing index zero-extension for Atomics operations.
| Assignee | ||
Comment 12•3 months ago
|
||
Compare-Exchange is implemented using a LR/SC loop, so the expected value needs
to be sign-extended to a word to ensure other bits in the high word are ignored.
The test case in part 13 fails without this change.
| Assignee | ||
Comment 13•3 months ago
|
||
Pass ZeroExtend32To64 to properly zero-extend the index for Atomics
operations. Otherwise we end up adding the sign-extended index, for example
0xFFFFFFFF80000000 instead of 0x80000000.
Comment 14•3 months ago
|
||
Comment 15•3 months ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/76721b4f58d5
https://hg.mozilla.org/mozilla-central/rev/40309fa2a158
https://hg.mozilla.org/mozilla-central/rev/2fcb0b9124ad
https://hg.mozilla.org/mozilla-central/rev/e951a4bf175c
https://hg.mozilla.org/mozilla-central/rev/fbc37029f083
https://hg.mozilla.org/mozilla-central/rev/20702b466582
https://hg.mozilla.org/mozilla-central/rev/35bdde524cc1
https://hg.mozilla.org/mozilla-central/rev/d6447c3bd5bc
https://hg.mozilla.org/mozilla-central/rev/5f23707971ed
https://hg.mozilla.org/mozilla-central/rev/1e106724a415
https://hg.mozilla.org/mozilla-central/rev/26b9c0e38800
https://hg.mozilla.org/mozilla-central/rev/7963a854d65c
https://hg.mozilla.org/mozilla-central/rev/b1f18bf91233
Updated•2 months ago
|
Description
•