-
Notifications
You must be signed in to change notification settings - Fork 396
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 full support for calls on z/OS and enable corresponding tests #4907
Conversation
Leaving this in draft mode as I still need to validate that I haven't broken OpenJ9 on z/OS, which I most certainly have, but the fix will be simple as soon as I test it. In the mean while this should be ready for review. I'll proceed and self-review the change to note the most important design decisions which we can discuss here. @genie-omr build all |
@@ -379,7 +379,7 @@ compileMethodFromDetails( | |||
// not ready yet... | |||
//OMR::MethodMetaDataPOD *metaData = fe.createMethodMetaData(&compiler); | |||
|
|||
startPC = compiler.cg()->getCodeStart(); | |||
startPC = (uint8_t*)compiler.getMethodSymbol()->getMethodAddress(); |
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 was the main change in thinking here. See the commit body (ab6d6a4) for a full description of why we made this change.
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.
To be explicit this is a design decision which I'd like @mstoodle and @aviansie-ben to comment on, and perhaps @Leonardo2718 as well. It is unfortunate we don't have a public API, because in that case getCodeStart
would likely be a private API internal to the compiler, and we would only provide one public API to extract the "pointer to a function" we compiled with OMR.
Do we agree with this approach? If not, any suggestions on an alternative?
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 approach seems fine to me.
I agree that having a single public API to extract the function pointer would be ideal. But I don't think that's a problem that needs to be solved here. The approach you've taken is reasonable given what we currently have, IMHO.
genLoadAddressConstant(cg(), callNode, reinterpret_cast<uintptrj_t>(fd), epReg); | ||
generateRSInstruction(cg(), TR::InstOpCode::getLoadMultipleOpCode(), callNode, aeReg, epReg, generateS390MemoryReference(epReg, 0, cg())); | ||
|
||
TR::Instruction* callInstr = new (cg()->trHeapMemory()) TR::S390RILInstruction(TR::InstOpCode::BRASL, callNode, raReg, fd->func, callSymRef, cg()); | ||
callInstr->setDependencyConditions(preDeps); |
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.
Loads the function's address from the function descriptor and dispatches the call.
#if defined(J9ZOS390) | ||
struct FunctionDescriptor | ||
{ | ||
uint64_t environment; | ||
void* func; | ||
}; | ||
|
||
FunctionDescriptor* fd = new FunctionDescriptor(); | ||
fd->environment = 0; | ||
fd->func = *entry; | ||
|
||
*entry = (void*) fd; | ||
#elif defined(AIXPPC) |
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.
Finally! This hack is now removed and we don't need to do anything special for z/OS. Once AIX gets support we can also remove the AIX piece as well.
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.
Sweet!
|
||
// The file we generate here is in the PPM image format which has a simple header describing how to interpret the | ||
// buffer. This string needs to be encoded as ASCII in the file generated, however on platforms such as z/OS whose | ||
// native encoding is not ASCII this is problematic. | ||
// | ||
// TODO (#4901): Use the port library to output the header bytes for PPM image file format |
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.
Linking this PR with #4901 so GitHub notes the link for future whenever we fix this.
Also suggesting @aviansie-ben for review as well as I cannot tag him on the GitHub interface. |
if (comp->getCurrentMethod() == NULL) | ||
{ | ||
comp->getMethodSymbol()->setMethodAddress(cg->getBinaryBufferStart()); | ||
} |
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 piece of code was alarming to me. Does anyone know why this exists? And why is it guarded by a getCurrentMethod
null check? When would this value ever be NULL
?
} | ||
cg->getAheadOfTimeCompile()->dumpRelocationData(); | ||
traceMsg(comp, "</relocatableDataCG>\n"); | ||
} |
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.
any chance you could split these changes into a separate commit? they interfere with appreciating the setup you've made here for a much better solution to the FD issue.
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 reason this formatting change was made is because the indentation in it's current state is very confusing [1], and at first sight one may think the:
if (comp->getCurrentMethod() == NULL)
{
comp->getMethodSymbol()->setMethodAddress(cg->getBinaryBufferStart());
}
piece of code is guarded by the if (cg->getAheadOfTimeCompile() &&
check, which is what I first thought, but upon a more careful inspection the indentation was hiding this is not the case.
If you wish to view that commit without whitespace changes GitHub can help here:
ab6d6a4?w=1
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.
907ae0c
to
7dc9546
Compare
@genie-omr build all |
9677c26
to
b14ad25
Compare
Just remembered my comment [1] to myself to revert some tests we disabled because of the lack of support for callouts. Now that we have them we can re-enable the tests. [1] #4719 (comment) |
@genie-omr build all |
Much to my surprise I was wrong. OpenJ9 works fine with this change. The reason is because I've validated OpenJ9 works perfectly fine with this change, hence I'm marking this PR as ready for review/merging. [1] https://github.com/eclipse/omr/blob/b03105e81b1b020900afbb2871cbd45aaaf8048c/compiler/z/codegen/SystemLinkage.hpp#L118-L120 |
In this change we rewrite the Call sample with a few enhancements to introduce all call types: - JIT to JIT - JIT to native - JIT to computed native - Native to JIT The test computation is still the same, i.e. we still compute a double sum, however we do it in several different ways so as to test calls both to and from JIT/native to ensure all paths are working as expected. This is particularly useful for platforms which have special handling of function pointers, such as AIX and z/OS. Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
Now that we have full support for calls on z/OS we can safely enable all Tril tests which were previously disabled. Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
OMR nor any downstream projects support 31-bit XPLINK to OS linkage, and the support is also not present in the rest of the compiler. This code block is slated for deprecation as we don't anticipate it being used. Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
The path for loading double arguments for outgoing calls was disabled within the `J9_PROJECT_SPECIFIC` ifdef, and as such double arguments were not being loaded for outgoing calls. We fix this by moving the case label outside of the ifdef. In addition there is no need to check for `getNumIntegerArgumentRegisters` before incrementing the GPR index, similarly to the integer cases since the `getIntegerArgumentRegister` API will already return the default value if the register index does not participate in the calling convention. Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
I had to rebase to absorb the changes in #4821 to use the new @genie-omr build all |
Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
I had to rebase again to fix conflicts introduced by removal of @genie-omr build all |
Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
@genie-omr build all |
@mstoodle @0xdaryl @Leonardo2718 any takers for a committer for this one? |
As per comment by @mstoodle (#4964 (comment)) I've added the patch from #4909 to this PR in 2e7226c so we have test coverage. Launching builds again. @genie-omr build all |
Looks like there are issues on the following builds: I'm going to back out 2e7226c from this PR and reopen #4909 for further investigation. |
2e7226c
to
0bd553a
Compare
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'm not done reviewing this yet, but here are some comments I have so far. Mostly minor stuff that doesn't necessarily have to be addressed here. I just wanted to write down my thoughts so far so I don't forget.
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 👍
@fjeremic I'm fine with the changes as they are. I did have a few questions but they are minor enough they don't need to be addressed here. I'll let you decide what to do with them.
TypeToString<TypeParam>::type, // args | ||
TypeToString<TypeParam>::prefix, // return | ||
TypeToString<TypeParam>::prefix, //call | ||
reinterpret_cast<uintmax_t>(static_cast<TypeParam(*)(TypeParam)>(callee_entry_point)), // address |
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.
Hm.... I'm not completely sure if that inner static_cast
is needed.
As I recall, that cast is needed to work around a bug in MSVC (I think) involving incorrect handling of pointers to template functions. Technically, callee_entry_point
is not a template function. However, it's type is template type dependent. So, I'm not sure if it triggers the same bug.
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.
You're right. All the builds passed. Fixed in 11c8008
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.
If it worked in this one location, I would think that it should also work for every other test that uses callee_entry_point
.
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.
Right. I've force pushed the fix to cover all uses in fa96327
} | ||
|
||
template <typename T> | ||
T (*getJitCompiledMethodReturning1stArgument())(T) { |
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.
Man, gotta love that function signature 😝
@@ -379,7 +379,7 @@ compileMethodFromDetails( | |||
// not ready yet... | |||
//OMR::MethodMetaDataPOD *metaData = fe.createMethodMetaData(&compiler); | |||
|
|||
startPC = compiler.cg()->getCodeStart(); | |||
startPC = (uint8_t*)compiler.getMethodSymbol()->getMethodAddress(); |
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 approach seems fine to me.
I agree that having a single public API to extract the function pointer would be ideal. But I don't think that's a problem that needs to be solved here. The approach you've taken is reasonable given what we currently have, IMHO.
@Leonardo2718 thanks for the review. I still want to address your earlier points. I think there is no better time do implement such work than now. I'll have fixes for those in the next day. Apologies for the slow progress. |
Well, if we're going to apologize for slow progress, I should apologies for taking so long to review. 😅 |
Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
6ea5f84
to
13a5b43
Compare
@genie-omr build all |
All review comments addressed. Please see each review for a reference to a commit which addresses the review concern. @Leonardo2718 do you want to be a committer for this one? |
Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
These helper macros will skip tests based on architecture and operating system combinations. Signed-off-by: Filip Jeremic <fjeremic@ca.ibm.com>
13a5b43
to
cf60a96
Compare
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 👍
@genie-omr build all I want to merge this tomorrow by EOD. If anyone still wants to review this change, please speak up before then. |
Times up! Merging now. |
This PR contains a series of commits which enables full support for JIT <-> native calls on z/OS. The change appears rather large due to the amount of test code that was enhanced to validate the support. There was also other issues encountered during development which were fixed. Please see the commit descriptions for details on what each change does and why.
The "meat" of the support can be found in the two commits titled:
These two commits give us the support and are not very large changes all in all.
Issue: #4719