Conversation
script to check it.
|
The PR is ready for review. Sometimes the CI job |
These are the runs that failed. Error messages are: The hosted runner: GitHub Actions 3 lost communication with the server. Anything in your workflow that terminates the runner process, starves it for CPU/Memory, or blocks its network access can cause this error.The runner has received a shutdown signal. This can happen when the runner service is stopped, or a manually started runner is canceled.If this only happened in a certain period of time, it simply could be a Github issue. |
|
The runner has received a shutdown signal. This can happen when the runner service is stopped, or a manually started runner is canceled.There are many discussions about this error for Github runners. It usually means the resources consumed in the process exceeded the limits. It could be related with the code change in the PR (if it consumes more memory or more CPU). It could also be changes in the Github runner specs. The simplest thing to try is to create another PR without any code change, and see if we see this error. |
wks
left a comment
There was a problem hiding this comment.
LGTM.
I also left a comment, but it may be too pedantic.
This PR adds compressed oops support for mmtk-openjdk, and enables it by default.
Implementation strategy and workarounds
Heap layout and compression policy
This PR uses the
Edgetype to abstract over the compressed edge and uncompressed edge. Object field loads and stores for uncompressed edges work as before. Loads and stores for compressed edges will involve an additional compression and decompression step.In general, this is the function to decode a 32-bit compressed pointer to its uncompressed form:
OpenJDK has a few optimizations to reduce the add and shift operations in JIT-compiled code, this PR supports them all:
0x4000_0000..0x1_0000_0000, it is possible to totally remove the add and the shift. The compressed and uncompressed forms are identical.BASE = 0andSHIFT = 0for this case.0x4000_0000..0x8_0000_0000, it is possible to remove the add.BASE = 0andSHIFT = 3for this case.For cases (1) and (2), the jit compiled code will contain less or even no encoding/decoding instructions, and hence improve the mutator performance. However, in Rust code, we still do the add and shift unconditionally, even when
BASEorSHIFTis set to zero.NULL pointer checking
Generally,
BASEcan be any address as long as the memory is not reserved by others. However,BASEmust be smaller thanHEAP_START, otherwiseHEAP_STARTwill be encoded as0and be treated as a null pointer.Same as openjdk, we set
BASEtoHEAP_START - 4096to solve this issue.Type specialization
Since we only support one edge type per binding, providing two
OpenJDKEdgein oneMMTKinstance is not possible.This PR solves the issue by specializing almost all the types in the binding, with a
const COMPRESSED: boolgeneric type argument. It provides twoMMTKsingletons:MMTK<OpenJDK<COMPRESSED = true>>andMMTK<OpenJDK<COMPRESSED = false>>.MMTK<OpenJDK<COMPRESSED = true>>will have theOpenJDKEdge<COMPRESSED = true>edge that does the extra pointer compression/decompression.The two MMTK singletons are wrapped in two lazy_static global variables. The binding will only initialize one of them depending on the OpenJDK command-line arguments. Initializing the wrong one that does not match the
UseCompressedOopsflag will trigger an assertion failure.Pointer tagging
When compressed oops is enabled, all the fields are guaranteed to be compressed oops. However, stack or other global root pointers may be still uncompressed. The GC needs to handle both compressed and uncompressed edges and be able to distinguish between them.
To support this, this PR treats all the root
OpenJDKEdge<COMPRESSED = true>s as tagged pointers. If the 63-th bit is set, this indicates that this edge points to a 64-nit uncompressed oop, instead of a compressed oop. And theOpenJDKEdge::{load, store}methods will skip the encoding/decoding step.For object field edges, the encoding is performed unconditionally without the pointer tag check.
When compressed oops is disabled, there is no pointer tag check as well.
Embedded pointers
Some (or probably all) pointers embedded in code objects are also compressed. On x64, it is always compressed to a
u32integer that sits in an unaligned memory location. This means we need to (1) treat them as compressed oops just like other roots. (2) still performs the unaligned stores and loads.However, for other architectures, the compressed embedded pointers may not be encoded as a
u32anymore.Compressed
Klass*pointersWhen
UseCompressedOopsis enabled, by default it also enablesUseCompressedClassPointers. This will make theKlass*pointer in the object header compressed to au32as well. This PR supports class pointer compression as well.However, class pointer compression is only supported and tested when the compressed oops is enabled. The two flags must be enabled or disabled together. Enabling only one of them is not tested, not supported, and will trigger a runtime assertion failure.
Performance results
SemiSpace
Immix