-
Notifications
You must be signed in to change notification settings - Fork 722
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
Serializing and caching results of AOT compilations at the JITServer #13962
Serializing and caching results of AOT compilations at the JITServer #13962
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I only have some minor comments
In a follow on PR we may want to add a filter through client command line options, about which methods should be stored in the AOT server side cache: |
There is a merge conflict due to my latest fix. |
Please don't force push, in the middle of a review right now :) |
Yes, that would be helpful for diagnostics etc., I'll add the option in a future PR. Should there be separate options for store and load or just a single one for bypassing AOT cache altogether for a given method? |
I guess we also need to wait until #13973 is merged because JITServer tests would currently fail. |
Yes, I will not run tests before #13973 is merged and this code rebased. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks reasonable; however I have a few questions/suggestions. Also, you should add doxygen comments for all the new APIs you added (including the helper methods).
void | ||
J9::Compilation::addSerializationRecord(const AOTCacheRecord *record, uintptr_t reloDataOffset) | ||
{ | ||
TR_ASSERT(_aotCacheStore, "Trying to add serialization record for compilation that is not an AOT cache store"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this TR_ASSERT_FATAL
; TR_ASSERT
isn't on by default.
@@ -40,9 +40,11 @@ namespace J9 { typedef J9::Compilation CompilationConnector; } | |||
#include "infra/Statistics.hpp" | |||
#include "env/CompilerEnv.hpp" | |||
#include "env/OMRMemory.hpp" | |||
#include "env/PersistentCollections.hpp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to guarded by #ifdef J9VM_OPT_JITSERVER
.
acaRecord->setClassChainIdentifyingLoaderOffsetInSharedCache(reloTarget, classChainIdentifyingLoaderOffsetInSharedCache, | ||
self(), classChainRecord); | ||
acaRecord->setClassChainForInlinedMethod(reloTarget, classChainOffsetInSharedCache, self(), classChainRecord); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to use two different Class Chain records here? Because these are two different class chains.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same goes for all other places below that have setClassChainIdentifyingLoaderOffsetInSharedCache
and setClassChain*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AOT cache identifies class loaders by name of the 1st loaded class, not by its class chain. This class loader ID is obtained from a class chain record as the class loader ID of the root class of the chain. The setter implementations in relocation records do the right thing and call addClassChainSerializationRecord()
for class chains and addClassLoaderSerializationRecord()
for class chains identifying loaders. I'll explain this in the doc comments that I'll add for the add*SerializationRecord()
methods.
J9::AheadOfTimeCompile::addClassSerializationRecord(const AOTCacheClassChainRecord *classChainRecord, | ||
const uintptr_t *romClassOffsetAddr) | ||
{ | ||
const AOTCacheClassRecord *record = classChainRecord ? classChainRecord->records()[0] : NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain how this is all laid out? classChainRecord
is of type
class AOTCacheClassChainRecord final : public AOTCacheListRecord<ClassChainSerializationRecord, AOTCacheClassRecord>
which means
const R *const *records() const { return (const R *const *)_data.end(); }
becomes
const AOTCacheClassRecord *const *records() const { return (const AOTCacheClassRecord *const *)_data.end(); }
where D _data
is now ClassChainSerializationRecord _data
.
Searching for end()
takes me to AOTSerializationRecord::end()
, which is
const uint8_t *end() const { return (const uint8_t *)this + size(); }
I don't really understand how the data is laid out, because at first glance this looks like we're going out of bounds.. I think this needs a bunch of documentation to describe how all of this fits together,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The layout of AOTCacheClassChainRecord
is as follows:
AOTCacheClassChainRecord
headerClassChainSerializationRecord
headerClassSerializationRecord
data: array of N class IDs- array of N
AOTCacheClassRecord
pointers
I'll add comments in JITServerAOTCache.hpp
to better describe the layout. I'll also move classChainRecord->records()[0]
to a separate helper method in AOTCacheClassChainRecord
.
{ | ||
uint32_t locationSize = 1; // see OMR::RuntimeAssumption::isForAddressMaterializationSequence | ||
if (reloFlags(reloTarget) & needsFullSizeRuntimeAssumption) | ||
locationSize = sizeof(uintptr_t); | ||
uint32_t locationSize = 1; // see OMR::RuntimeAssumption::isForAddressMaterializationSequence | ||
if (reloFlags(reloTarget) & needsFullSizeRuntimeAssumption) | ||
locationSize = sizeof(uintptr_t); | ||
createClassRedefinitionPicSite((void*)-1, (void*)reloLocation, locationSize, true, getMetadataAssumptionList(reloRuntime->exceptionTable())); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might as well fix up the position of the brackets as well. Also maybe add brackets for the if
clause.
This PR is ready for a rebase because #13973 was merged. |
…ions Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
80c116c
to
428c643
Compare
Addressed the comments and rebased. |
Jenkins compile all jdk8 |
Let's wait for the compilation tests. Frankly, I thought they would be done by now. |
aarch64_linux compilation is failing with
|
Oops, copy-paste mistake during refactoring. Will push the fix shortly. |
For each client SCC offset written into AOT relocation data during out-of-process AOT compilations, we remember the corresponding AOT cache record (creating it on demand if necessary) and the offset into AOT relocation data where the SCC offset is stored. The list of <AOT cache record, relocation data offset> pairs is stored in the compilation object. This list will be used to store the serialized AOT method in the JITServer AOT cache at the end of the compilation. Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Check that the AOT method header version is correct and that each SCC offset being updated is located within AOT relocation data. Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
…tores Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Information from the client needed to create the record (class chain, etc.) and method index are included with the compilation request. Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
The code previously incorrectly assumed that the only case when the client can abort the compilation early is when it replies to the message requesting the whole CHTable, at which point the last processed critical sequence number is not yet updated in the client session. Aborts can also occur when requesting uncached classes or VMInfo from the client, which can happen after the sequence number is already updated. To distinguish these two cases, we add a flag to keep track of whether the sequence number was already updated or not. Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
…dRemote Move the newly added fields used by out-of-process compilations stored in AOT cache to CompilationInfoPerThreadRemote to reduce the memory overhead - there is one instance per server compilation thread rather than per compilation queue entry on both the server and the client. Signed-off-by: Alexey Khrabrov <khrabrov@cs.toronto.edu>
428c643
to
287721e
Compare
Done. By the way, most of the code in |
Jenkins compile all jdk8 |
jenkins test sanity plinuxjit,xlinuxjit,zlinuxjit jdk11 |
jenkins test sanity plinuxjit,xlinuxjit,zlinuxjit jdk11 |
Tests on zLinux passed.
|
Actually, the tests on xLinux appear to have passed now: https://openj9-jenkins.osuosl.org/job/PullRequest-OpenJ9/1241/ |
Jenkins compile all jdk8 |
All compilation tests have passed as well: https://openj9-jenkins.osuosl.org/job/PullRequest-OpenJ9/1247/ |
@dsouzai If you agree, please approve this PR. Thanks |
This PR implements serialization of AOT methods compiled at the JITServer and storing them in its AOT cache.