Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for dependency tracking #20954

Merged
merged 1 commit into from
Jan 16, 2025

Conversation

cjjdespres
Copy link
Contributor

@cjjdespres cjjdespres commented Jan 16, 2025

Developer documentation for the dependency-based AOT load scheduling feature has been added to the doc/ folder.

@cjjdespres
Copy link
Contributor Author

Attn @mpirvu

@mpirvu mpirvu self-assigned this Jan 16, 2025
Copy link
Contributor

@mpirvu mpirvu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I spotted a couple of typos.


When a method is initialized, it goes through `jitHookInitializeSendTarget()` to receive an initial invocation count. Under count-based loading, that function will check to see if the method has a cached compiled counterpart in the local SCC. If so, it will receive a lower invocation count, controlled by the `-Xaot:scount` parameter. (The current default is 20). The method is then executed as usual; the purpose of the lower count is simply to trigger a compilation request for that method earlier than normal. The `preCompilationTasks()` will notice that the method has a corresponding cached AOT body in the SCC, and signal that an AOT load should be performed for that method.

The reason why the initial invocation count is not zero is that the JVM maybe in a different, incompatible state at the moment the method is loaded compared to when it was compiled. This is partly due to the larger invocation count a method will receive during the cold run (when the method was AOT-compiled and stored in the SCC in the first place) and partly due to natural variation in the evolution of the JVM state. At the time of compilation, the JIT may have been able to gather a lot of profiling information, resolve a lot of classes, and inline a lot of methods. This will improve the performance of the compiled code, but makes that code harder to relocate, because at load time the relo runtime must be able to re-acquire candidates for all of those classes and methods in the new JVM. Those classes might not be resolvable right when the method is initialized, so the `scount` provides a heuristic load delay to give the running application a chance to load the necessary classes and methods.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe --> may be


These dependencies are encoded in a "dependency chain" after the relocation records of the method are processed in `J9::AheadOfTimeCompile::processRelocations()`, and the chain will be stored in the local SCC. The compiled method will then be flagged as having its dependencies tracked, and an offset to the chain will be stored in the AOT method header. As an optimization, if a method has zero dependencies then no chain is stored in the SCC - we need the separate "tracks dependencies" flag to distinguish those methods from ones that do not track dependencies at all, because those latter methods must use traditional count-based loading.

As it happens, the only class load/initialization dependencies for a compiled method that need to be tracked are ones for class chain offsets that are mentioned in one of the relocation records of that method. These are the only classes that the relo runtime will want to resolve during relocation. For that reason, the dependencies are mostly gathered in `RelocationRecord.cpp`, in the methods that set the class chain offsets that are stored in the relo records. Specifically, a dependency is registered right next to every call to `J9::AheadOfTimeCompile::addClassSerializationRecord` and `J9::AheadOfTimeCompile::addClassChainSerializationRecord`, because those methods are what register all the class/class chain offset uses for JITServer AOT cache compilations (and so must cover every such use). Some dependency tracking also takes place in `SymbolValidationManager.cpp`, mostly related to well-known classes; instead of adding the contents of the entire well-known classes chain as dependencies, we instead only add those well-known class chain offsets that are actually used in the relocation records. This reduces the number of dependencies somewhat.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second "instead" is not needed: "... instead of adding the contents of the entire well-known classes chain as dependencies, we instead only add ..."

@mpirvu
Copy link
Contributor

mpirvu commented Jan 16, 2025

No testing required. Item can be merged.

@mpirvu mpirvu merged commit b3f30d5 into eclipse-openj9:master Jan 16, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants