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
8244938: Crash in foreign ABI CallArranger class when a test native function returns a nested struct #162
Conversation
👋 Welcome back mcimadamore! A progress list of the required criteria for merging this PR into |
Webrevs
|
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.
A nice chunk of code getting vaporized 😄. As mentioned offline, the only problem I see is with structs where the fields cross eightbyte boundaries (for instance when using packed structs).
for (MemoryLayout m : group.memberLayouts()) { | ||
groupByEightBytes(m, offset, groups); | ||
if (group.isStruct()) { | ||
offset += m.byteSize(); | ||
} | ||
} |
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 loop is duplicated in the other method above. Might want to move to helper method.
@mcimadamore This change now passes all automated pre-integration checks, type
Since the source branch of this PR was last updated there have been 2 commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid automatic rebasing, please merge ➡️ To integrate this PR with the above commit message to the |
/integrate |
@mcimadamore The following commits have been pushed to foreign-abi since your change was applied:
Your commit was automatically rebased without conflicts. Pushed as commit 32d1f6c. |
This is a nasty issue with the SysV struct classification algorithm (which is rather complex).
The algortigm as specified, is designed to work on 8-byte chunks at a time (the SysV spec calls them
eighbytes
). This means that when there are nested structs, some structs might need to be broken apart to implement the algorithm correctly. Consider this case:Here we have an int field (
x
) and then two nested int fields (namely,y
andz
).The currently implemented logic, sees the first field, and classifies it as
INTEGER
. It then calls the classification recursively on the second field, which is a struct. Since the struct fits in 8 bytes, the recursive classification yields a single class, namely INTEGER. The outer classification logic then attempts two merge the two INTEGER classes (one from the first field, the other from the struct), and obtain a single INTEGER class as a result. This is a wrong result, as 12 bytes cannot obviously fit in a single eightbyte.To address this issue I first considered flattening structs, but then I quickly gave up, since it was pretty messy to make sure that flattening worked correctly with respect to unions (e.g. structs inside unions).
I then settled on a simpler scheme: since the classification logic is meant to work on one eightbyte at a time, I just wrote a routine that parses the incoming
GroupLayout
and breaks it apart into an array ofArgumentClassImpl
, where the size of the array is the number of eightbytes into which the group is to be classified.We recursively scan the layout, trying to find all the fields, and keeping track of their offsets. Eventually, when we come to leaves layouts (values) we add their corresponding ArgumentClassImpl to the array slot that corresponds to the eightbyte associated with the offset being considered.
Once this processing is done, classifying the struct is a breeze, as what's left to do is simply to merge all the classes in a single eightbyte slot (which can be done with a simple reduce step).
Note: for this logic to work, we have to assume that all value layouts in the group are not bigger than 8 bytes. In practice this is not a big issue, since bigger value layouts were not supported anyway. I also believe it won't be an issue moving forward, since we can simply make sure that e.g. the SysV type
__int128
is modelled with this layout:Or that
long double
is handle like this:And so forth for vector types. In other words, rather than making the classification logic more complex, we can simply define the ABI layout constants accordingly, so that they are already broken up into 8-byte chunks.
Progress
Issue
Reviewers
Download
$ git fetch https://git.openjdk.java.net/panama-foreign pull/162/head:pull/162
$ git checkout pull/162