This class is similar to std::shared_mutex except it is safe for the
same thread to increment or decrement the ref counter multiple times.
This can be passed to regular std locks.
This will be required with the code object cache service soon.
Creates a pool allocator for OpcodeDispatcher and IRCompaction that
shares memory allocations between threads in a pool and supports
reclaiming stale allocations from participating threads.
A thread will use a heuristic to keep its claimed memory allocation
around if it is allocating a lot of code. If it slows down then it will
start putting the memory allocation back in to the thread pool.
Additionally if the allocation has been "disowned" and gone to sleep
while still retaining the allocation, then another thread can inspect
these stale allocations and reclaim it from the idling thread. Saving
further memory.
This needs some more work and cleanup but this is an interesting concept
that saves a decent amount of memory even in a basic test.
Causes teeworlds' title screen to go from 754MB to 599MB in my simple
test. 79.4% the memory usage is a good start.
Since we are masking signals before compiling code, we no longer will
receive a signal in the middle of compiling code.
This makes the compile service never be invoked so we can just remove
it.
We still have some locations in the syscall handling that isn't signal
safe, but compileservice wouldn't have fixed those anyway.
For 128-bit divides, we can very quickly check at runtime if we can
avoid the long divide and just do a 64-bit divide.
For unsigned just check if the top bits are all zero.
For signed just check if the top bits match bit 63 of the lower bits.
Additionally, keep the long divide handlers inside of the dispatcher.
This keeps the majority of the code bloat out of the code block itself,
significantly reducing block size for something doing these divides.
Also a fairly large icache improvement from this.
Hard performance number improvements here are hard to get since it
heavily depends on the application, also only occurs on x86-64.
Seems to have helped FTL and Dead Cells performance quite a bit though.
For the JIT cores we don't need to keep IR around, it's only necessary
for the Interpreter. So once the AOT IR service is done dealing with the
IR, check to see if we can delete it.
This causes teeworld's title screen memory usage to go from 730MB to
566MB. 77.5% the memory usage there.
This is effectively an infinite memory leak if the codespace wasn't ever
overwritten or invalidated. So larger memory usage programs would end up
having a larger impact.
In some cases we can generate more optimal code if we have more
information about a syscall which number gets const-propagated.
In particular optimizing through syscalls, not synchronizing state, and
never returning.
- Noreturn is used by a syscall that never returns, like exit.
This means that it never needs to try and synchronize state coming back
- Not synchronizing state and optimizing through syscalls
Useful for syscalls that don't read the state past arguments and only
returns a value.
This allows x87 fallbacks to be loaded from the upcoming code cache
without relocations.
Only 40 pointers necessary to store and means x87 code won't hit
relocations heavily.
Probably improves performance slightly on the x86 host side but should
be neglible.
Needs #1574 and #1575 merged first.
Just like the previous AArch64 JIT.
These pointers are process or thread specific depending on the pointer
and should be loaded from the State object.
Performance here might slightly increase.
This is required for code cache on x86
Needs #1574 merged first.
These pointers are process or thread specific depending on which pointer
it is.
All of these pointers end up getting used inside of the JIT blocks
themselves and with code caching would result in a ton of relocations
occuring inside the code.
The pointers used within the dispatcher don't currently matter since I'm
not expecting to cache the dispatcher itself. It's only a page per
thread after all. This does move us significantly closer towards using a
single dispatcher for all threads though.
The performance impact of this change is unlikely to be felt at all,
some locations have less code generation which could improve perf
slightly. Some locations move from a 1-3 cycle constant calculation to a
4 cycle load, hard to be felt since it gets hidden by other
instructions.
x86-64 JIT will be added soon after this
The host provided siginfo_t definition can vary depending on the build
environment.
What doesn't change however is how the data is laid out.
It's always 128bytes, The first three 32-bit words are always known.
The 64-bit host side always has an additional 32-bit pad member.
Then the remaining bytes is the sifields.
This table is particularly terrible. CRC32 is the first instruction in
this table that needs either prefix `72h` OR `66h && F2h`
For 8bit CRC32, this ignores the 66h operand size override prefix.
- But our table decoding didn't handle this
For 16bit/32bit/64bit CRC32 this behaviour changes depending on 66h
prefix AND REX.W
- 66h prefix is ignored when REX.W is set, always 64bit but it falls
down the other table path
This is an absolutely weird edge case that nobody should hit, but here
we are.
Brings along a bunch of enhancements and ensures we always build against
the latest version.
Also fixes up a few issues that arose due to changes in fmt
Due to the way this syscall handles siginfo_t, we only need to shift
data through the padding.
This is due to the syscall not allowing you to send siginfo_t with
si_code being positive. Which is what the kernel uses to interpret the
data if it is reinterpreting it.