Skip to content

Improve linkToVirtual() and linkToInterface() dispatch - #17850

Merged
gacholio merged 2 commits into
eclipse-openj9:masterfrom
jdmpapin:linkto-virt-if
Aug 14, 2023
Merged

Improve linkToVirtual() and linkToInterface() dispatch#17850
gacholio merged 2 commits into
eclipse-openj9:masterfrom
jdmpapin:linkto-virt-if

Conversation

@jdmpapin

Copy link
Copy Markdown
Contributor
  • Remove the direct- and non-interface virtual-dispatch cases from linkToInterface() in the VM. They used to be needed, but they've been dead since 425a1f1.

  • Implement a recognized call transformation for linkToInterface(). The generated IL need only handle actual itable-based dispatch, and it does not introduce any control flow in the IL. This avoids doing a J2I transition whenever the callee is compiled.

  • Change jitLookupDynamicPublicInterfaceMethod (now used in the above-mentioned transformation) to take the MemberName instead of the interface class and iTable index. There's no need to generate IL to find them, since the helper can do that on its own. Cases where they are constant might get slightly slower, but the right way to improve those cases will be to refine and possibly inline linkToInterface().

  • Remove the direct-dispatch case from linkToVirtual() in the VM and in the IL generated by recognized call transformer. That case used to be needed, but like the removed linkToInterface() cases, it has been dead since 425a1f1.

  • Remove the interface-dispatch case from linkToVirtual() in the VM and in the IL generated by recognized call transformer. MemberName.vmindex is no longer a pointer to the J9JNIMethodID, but is now instead the vTable offset for invokevirtual, the iTable index for invokeinterface, and -1 for invokespecial and invokestatic. The interface dispatch case in linkToVirtual() used to occur whenever vmtarget was inherited from an interface. Now MemberName resolution/initialization detects that scenario and sets vmindex to the correct vTable offset for clazz so that linkToVirtual() can dispatch the call the same way as any other. Note that in combination with the previous point, this means that the linkToVirtual() recognized call transformation no longer introduces control flow into the IL.

  • Refine linkToVirtual() calls in inliner and method handle transformer even when vmtarget has been inherited from an interface. Virtual calls to such methods can occur naturally in the bytecode, and the compiler is able to deal with them.

  • Delete jitLookupDynamicInterfaceMethod, since it's no longer used.

@jdmpapin

Copy link
Copy Markdown
Contributor Author

Requesting review from @vijaysun-omr and @0xdaryl for JIT, and from @gacholio for VM

Comment thread runtime/codert_vm/arm64nathelp.m4 Outdated
Comment thread runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp Outdated
@gacholio

Copy link
Copy Markdown
Contributor

@babsingh Please look over the VM changes.

@gacholio
gacholio requested a review from babsingh July 26, 2023 16:55
@jdmpapin

Copy link
Copy Markdown
Contributor Author

Pushed a slight correction to a comment

@gacholio gacholio left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me.

@jdmpapin

Copy link
Copy Markdown
Contributor Author

Rebased to fix the CommunicationStream::MINOR_NUMBER conflict

@babsingh babsingh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For functional verification, my recommendation is jekins test sanity.functional,extended.functional,sanity.system,sanity.openjdk,extended.openjdk alinux64 jdk17,jdk21 and a compile on Windows. Deliberate typo in jekins -> jenkins to avoid launching the PR builds.

Comment thread runtime/oti/j9nonbuilder.h Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/vm/BytecodeInterpreter.hpp Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/util/hshelp.c Outdated
Comment thread runtime/oti/util_api.h Outdated
Comment thread runtime/oti/util_api.h Outdated
@babsingh

Copy link
Copy Markdown
Contributor

@fengxue-IS Can you please also review the MethodHandleNatives and associated changes?

@babsingh
babsingh requested a review from fengxue-IS July 27, 2023 20:18
Comment thread runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp Outdated
Comment thread runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp Outdated
Comment thread runtime/util/hshelp.c Outdated
@jdmpapin

Copy link
Copy Markdown
Contributor Author

Pushed changes to address review comments

@0xdaryl

0xdaryl commented Jul 29, 2023

Copy link
Copy Markdown
Contributor

JIT changes look ok after my first pass through.

Comment thread runtime/compiler/control/JITClientCompilationThread.cpp Outdated

@babsingh babsingh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM.

@mpirvu mpirvu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

JITServer related changes look good.

@gacholio

gacholio commented Aug 2, 2023

Copy link
Copy Markdown
Contributor

jenkins compile win jdk8,jdk21

@gacholio

gacholio commented Aug 2, 2023

Copy link
Copy Markdown
Contributor

jenkins test sanity.functional,extended.functional,sanity.system,sanity.openjdk,extended.openjdk alinux64 jdk17,jdk21

@jdmpapin

jdmpapin commented Aug 2, 2023

Copy link
Copy Markdown
Contributor Author

Taking a look at what's going on with this on AArch64

@jdmpapin

jdmpapin commented Aug 2, 2023

Copy link
Copy Markdown
Contributor Author

Corrected the number of parameters for jitLookupDynamicPublicInterfaceMethod in *nathelp.m4. I looked for changes specific to AArch64, and the only such change was in arm64nathelp.m4, where I noticed that the parameter count was wrong. Since it was that way on every platform, I'm surprised it didn't cause more widespread failures, but I'm hoping anyway that it was the cause of the AArch64 failures in the PR build

@jdmpapin

jdmpapin commented Aug 2, 2023

Copy link
Copy Markdown
Contributor Author

Oh, I missed that tests in the PR builds had been running only on AArch64 to begin with

@jdmpapin
jdmpapin marked this pull request as draft August 2, 2023 19:34
@jdmpapin

jdmpapin commented Aug 2, 2023

Copy link
Copy Markdown
Contributor Author

I'm doing some additional testing. Converted to draft in the meantime

@jdmpapin

jdmpapin commented Aug 3, 2023

Copy link
Copy Markdown
Contributor Author

OK, sorry for the confusion here. Because there had been so many failures, all on AArch64, and because I hadn't realized it was running only on AArch64 to begin with, I assumed that I had caused the failures, but after looking through them now I think they're unrelated to my changes.

We have these two known issues:

All of the remaining failures were in DatagramChannel, which I think is due to some kind of machine/network problem. Not everything has already been captured verbatim in an issue, but I've done my best to link to similar failures where possible. It seems to me that we don't run extended.openjdk very often.

Additionally, there were no crashes, but I expect that any failures caused by this PR would likely be crashes.

@jdmpapin
jdmpapin marked this pull request as ready for review August 3, 2023 17:59
@gacholio

gacholio commented Aug 3, 2023

Copy link
Copy Markdown
Contributor

jenkins test sanity.functional,extended.functional,sanity.system,sanity.openjdk,extended.openjdk zlinux jdk17,jdk21

@gacholio

gacholio commented Aug 3, 2023

Copy link
Copy Markdown
Contributor

The test failures look like a GIT issue. I don't know how to restart the jobs without relaunching.

@pshipton

pshipton commented Aug 3, 2023

Copy link
Copy Markdown
Member

You look at https://openj9-jenkins.osuosl.org/job/Pipeline_Build_Test_JDK17_s390x_linux/1702/console and there are "Restart or Abort" links. I've restarted them.

@jdmpapin

jdmpapin commented Aug 4, 2023

Copy link
Copy Markdown
Contributor Author

Test_openjdk21_j9_sanity.functional_s390x_linux_Personal

  • testList_0 passed
  • testList_1 failed to fetch origin/pr/17850/merge ("the remote end hung up unexpectedly")

Test_openjdk21_j9_extended.functional_s390x_linux_Personal

  • testList_0 passed
  • testList_1 failed to fetch again

Test_openjdk21_j9_sanity.openjdk_s390x_linux_Personal

  • failed to fetch

Test_openjdk17_j9_extended.openjdk_s390x_linux_Personal:

  • security/infra/java/security/cert/CertPathValidator/certification/AmazonCA.java.AmazonCA: certificate revoked (as before)
  • com/sun/jndi/dns/ConfigTests/Timeout.java.Timeout: DNS error [... No route to host]

Test_openjdk21_j9_extended.openjdk_s390x_linux_Personal

  • AmazonCA again
  • SSLSocketParametersTest: java.rmi.NoSuchObjectException: no such object in table (as before)

The Restart links that Peter mentioned don't seem to be working for me, maybe because the Pipeline_Build_Test_... jobs have finished? For the ones that hit network errors with git, I'll restart them here

@jdmpapin

jdmpapin commented Aug 4, 2023

Copy link
Copy Markdown
Contributor Author

Jenkins test sanity.functional,extended.functional,sanity.openjdk zlinux jdk21

@jdmpapin

jdmpapin commented Aug 9, 2023

Copy link
Copy Markdown
Contributor Author

In extended.functional, there was one failure. It's a timeout when testing -XX:+ExitOnOutOfMemoryError:

Testing: Verify -XX:+ExitOnOutOfMemoryError behaves as expected with OutOfMemoryError
Test start time: 2023/08/04 20:17:28 Coordinated Universal Time
Running command: "/home/jenkins/workspace/Test_openjdk21_j9_extended.functional_s390x_linux_Personal_testList_0/openjdkbinary/j2sdk-image/bin/java"   -Xdump -Xmx64m -XX:+ExitOnOutOfMemoryError -cp "/home/jenkins/workspace/Test_openjdk21_j9_extended.functional_s390x_linux_Personal_testList_0/aqa-tests/TKG/../../jvmtest/functional/cmdLineTests/cmdLineTest_J9tests/cmdLineTest_J9tests.jar" OnOutOfMemoryErrorTest
Time spent starting: 1 milliseconds
***[TEST INFO 2023/08/04 20:27:28] ProcessKiller detected a timeout after 600000 milliseconds!***

I believe this is #13722


In sanity.openjdk there was also just one failure, which was a crash in OOMEInAQS:

[2023-08-04T22:18:40.450Z] JVMDUMP013I Processed dump event "systhrow", detail "java/lang/OutOfMemoryError".
[2023-08-04T22:18:40.450Z] Exception in thread "Attach API wait loop" java/lang/OutOfMemoryError: Java heap space
[2023-08-04T22:18:40.450Z] 	at java/lang/Throwable.printStackTrace (java.base@21-internal/Throwable.java:554)
[2023-08-04T22:18:40.450Z] 	at java/lang/Throwable.printStackTraceHelper (java.base@21-internal/Throwable.java:338)
[2023-08-04T22:18:40.450Z] 	at java/lang/Throwable.printStackTrace (java.base@21-internal/Throwable.java:307)
[2023-08-04T22:18:40.450Z] 	at java/lang/Throwable.printStackTrace (java.base@21-internal/Throwable.java:250)
[2023-08-04T22:18:40.450Z] STATUS:Passed.
[2023-08-04T22:18:40.450Z] Unhandled exception
[2023-08-04T22:18:40.450Z] Type=Segmentation error vmState=0x00040000

This one looks to be #16659


The other two failing checks are just the extended.openjdk tests that I described previously, since I didn't restart those.

@jdmpapin

jdmpapin commented Aug 9, 2023

Copy link
Copy Markdown
Contributor Author

I believe that all of the failures have been accounted for

@gacholio

gacholio commented Aug 9, 2023

Copy link
Copy Markdown
Contributor

Are we waiting for @0xdaryl to review?

@jdmpapin

jdmpapin commented Aug 9, 2023

Copy link
Copy Markdown
Contributor Author

Ah, yes, I think so

@0xdaryl

0xdaryl commented Aug 14, 2023

Copy link
Copy Markdown
Contributor

Please fix merge conflicts. Otherwise, looks good to me.

This code was duplicated in multiple methods of J9::TransformUtil.
- Remove the direct- and non-interface virtual-dispatch cases from
  linkToInterface() in the VM. They used to be needed, but they've been
  dead since 425a1f1.

- Implement a recognized call transformation for linkToInterface().
  The generated IL need only handle actual itable-based dispatch, and it
  does not introduce any control flow in the IL. This avoids doing a J2I
  transition whenever the callee is compiled.

- Change jitLookupDynamicPublicInterfaceMethod (now used in the above-
  mentioned transformation) to take the MemberName instead of the
  interface class and iTable index. There's no need to generate IL to
  find them, since the helper can do that on its own. Cases where they
  are constant might get slightly slower, but the right way to improve
  those cases will be to refine and possibly inline linkToInterface().

- Remove the direct-dispatch case from linkToVirtual() in the VM and in
  the IL generated by recognized call transformer. That case used to be
  needed, but like the removed linkToInterface() cases, it has been dead
  since 425a1f1.

- Remove the interface-dispatch case from linkToVirtual() in the VM and
  in the IL generated by recognized call transformer. MemberName.vmindex
  is no longer a pointer to the J9JNIMethodID, but is now instead the
  vTable offset for invokevirtual, the iTable index for invokeinterface,
  and -1 for invokespecial and invokestatic. The interface dispatch case
  in linkToVirtual() used to occur whenever vmtarget was inherited from
  an interface. Now MemberName resolution/initialization detects that
  scenario and sets vmindex to the correct vTable offset for clazz so
  that linkToVirtual() can dispatch the call the same way as any other.
  Note that in combination with the previous point, this means that the
  linkToVirtual() recognized call transformation no longer introduces
  control flow into the IL.

- Refine linkToVirtual() calls in inliner and method handle transformer
  even when vmtarget has been inherited from an interface. Virtual calls
  to such methods can occur naturally in the bytecode, and the compiler
  is able to deal with them.

- Delete jitLookupDynamicInterfaceMethod, since it's no longer used.
@jdmpapin

Copy link
Copy Markdown
Contributor Author

Rebased to fix the merge conflict with CommunicationStream::MINOR_NUMBER

Range diff

@gacholio
gacholio merged commit 1b26a8c into eclipse-openj9:master Aug 14, 2023
TR_ASSERT(haveAccess(), "jniMethodIdFromMemberName requires VM access");
return (J9JNIMethodID *)J9OBJECT_U64_LOAD(vmThread(), memberName, vmThread()->javaVM->vmindexOffset);
}
*out = {};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This doesn't compile on z/OS:

13:10:07  "/jenkins/workspace/Build_JDK17_s390x_zos_Personal/openj9/runtime/compiler/env/VMJ9.cpp", line 4764.11: CCN5063 (S) The text "{" is unexpected.
13:10:07  CCN0793(I) Compilation failed for file /jenkins/workspace/Build_JDK17_s390x_zos_Personal/openj9/runtime/compiler/env/VMJ9.cpp.  Object file not created.
13:10:07  runtime/compiler/CMakeFiles/j9jit.dir/build.make:960: recipe for target 'runtime/compiler/CMakeFiles/j9jit.dir/env/VMJ9.cpp.o' failed
13:10:07  make[6]: *** [runtime/compiler/CMakeFiles/j9jit.dir/env/VMJ9.cpp.o] Error 12

@jdmpapin Is there another way to say this that will be accepted by older compilers?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should it be {0} perhaps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The text "{" is unexpected.

suggests that we might get the same error from {0}. I think {} should work as an initializer though. I'll try this:

MemberNameMethodInfo zero = {};
*out = zero;

and of course check to make sure that it compiles on z/OS

@jdmpapin jdmpapin Sep 7, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It looks like it should work to use

MemberNameMethodInfo zero = {0};

With {}, the build compiler complained that zero was potentially uninitialized

My personal z/OS build failed for a reason I don't understand. I think it's unrelated, but I've asked for some help confirming that my change builds. I'll open a PR as soon as I get confirmation

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants