-
Notifications
You must be signed in to change notification settings - Fork 728
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
Track methods with AOT bodies with dependencies #20599
Track methods with AOT bodies with dependencies #20599
Conversation
Attn @mpirvu. This is the warm run side of the dependency tracking. |
* entry will be the offset itself (which necessarily has a set low bit), and if the class only needs to be loaded | ||
* it will be the offset with the low bit cleared. * | ||
* The dependencies of an AOT method are encoded as an array of uintptr_t | ||
* values. The first entry is the number of entries after the first, the |
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 original documentation said the first entry was the total number of entries, but I actually had the dependencies set up similarly to the well-known classes chain, where the first entry is the number of subsequent entries.
if (isClassLoad) | ||
entry->_loadedClasses.insert(ramClass); | ||
{ | ||
checkForSatisfaction(offsetEntry->_waitingLoadMethods); |
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.
This should only be run if there have been no previous loads for this offset
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.
Does this mean that the code needs some modification?
auto entry = getOffsetEntry(offset, isClassLoad); | ||
TR_ASSERT(entry || !isClassLoad, "Class %p offset %lu initialized without loading"); | ||
auto offsetEntry = getOffsetEntry(offset, isClassLoad); | ||
TR_ASSERT(offsetEntry || !isClassLoad, "Class %p offset %lu initialized without loading", ramClass, offset); |
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.
This isn't accurate - I check that ramClass
matches its cached version for loads only, so if this isn't a load, I need to check that ramClass
is in offsetEntry->_loadedClasses
. If it isn't, then it was intentionally not added when it was loaded.
if (isClassLoad) | ||
entry->_loadedClasses.insert(ramClass); | ||
{ | ||
checkForSatisfaction(offsetEntry->_waitingLoadMethods); |
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.
Does this mean that the code needs some modification?
a7a9f91
to
9ca5d97
Compare
Other than those corrections, I also added a fix in |
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.
Can the code handle the situation when two j9classes have the same ROMClass?
Say, I have an AOT method that depends on two ROMClasses and then I have two load operations of two different j9classes but with the same ROMClass, matching the dependency. Would the code wrongly decrement the number of outstanding dependencies to 0 and trigger a compilation?
} | ||
|
||
void | ||
TR_AOTDependencyTable::eraseOffsetEntryIfEmpty(const OffsetEntry &entry, uintptr_t offset) |
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.
Ideally, we would have an iterator as parameter that would capture both the entry and the offset because they come same hashtable entry. Maybe refine later.
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.
Yes, it's not the most elegant.
For loads, I don't think so. One of the loads would trigger For initializations, there might be a chance of that happening. If two threads try to initialize different classes at the same offset at the same time, the first thread will acquire the I'm not sure if two class initializations can get to that state at the same time. If there isn't a convenient way of making sure the second class initialization event is triggered only after the first is marked initialized, perhaps I could transfer the initialized class into a new |
jenkins compile all jdk17 |
When a method is initialized in jitHookInitializeSendTarget, the SCC will be checked to see if it has a stored AOT body that was compiled with tracked dependencies. If it does, and all of them are satisfied, the method will be given an initial count of 0. If not all of the dependencies are satisfied, the method will be tracked by the TR_DependencyTable until the dependencies are satisfied, at which point its count will be set to zero, triggering an AOT load on its next invocation. Signed-off-by: Christian Despres <[email protected]>
9ca5d97
to
8f5ae8d
Compare
jenkins compile all jdk8 |
The
I don't know why
The build was here. |
Windows builds failed because of lack of machines:
|
jenkins test sanity xlinux jdk23 |
When a method is initialized in jitHookInitializeSendTarget, the SCC will be checked to see if it has a stored AOT body that was compiled with tracked dependencies. If it does, and all of them are satisfied, the method will be given an initial count of 0. If not all of the dependencies are satisfied, the method will be tracked by the TR_DependencyTable until the dependencies are satisfied, at which point its count will be set to zero, triggering an AOT load on its next invocation.
Related: #20529