• Home
    • View
    • Login
    This page
    • Normal
    • Export PDF
    • Page Information

    Loading...
  1. Dashboard
  2. Undefined Space
  3. HotSpot
  4. JDK-8247536 Support pre-generated MethodHandle LambdaForms in CDS

Page History

Versions Compared

Old Version 6

changes.mady.by.user Yumin Qi

Saved on Jul 08, 2020

compared with

New Version 7

changes.mady.by.user Ioi Lam

Saved on Aug 12, 2020

  • Previous Change: Difference between versions 5 and 6
  • Next Change: Difference between versions 7 and 8
  • View Page History

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Improve start-up time by storing pre-generated LambdaForm handlers in an application-specific CDS archive.

Background

In JDK-8086045 (Improve the java.lang.invoke first initialization costs), the JDK can reduce the number of dynamically generated LambdaForm  LambdaForm classes. Here's an example:

...

The input of generateDirectMethodHandleHolderClassBytes comes from the defaultthe default_jli_trace.txt file that is generated in GenerateLinkOptData.gmk:

...

Code Block
$ grep invokeSpecialIFC ./support/link_opt/default_jli_trace.txt
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC L3I_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC LLI_I (fail)

$ images/jdk/bin/javap  'java.lang.invoke.DirectMethodHandle$Holder' | grep invokeSpecialIFC
  static int invokeSpecialIFC(java.lang.Object, java.lang.Object, java.lang.Object, int);
  static int invokeSpecialIFC(java.lang.Object, java.lang.Object, int);

The methods in DirectMethodHandle$Holder in DirectMethodHandle$Holder are used in InvokerBytecodeGenerator.java when compiling for LambdaForms:

...

  • We cannot store all possible LambdaForm handlers in the standard JDK image – we cannot enumerate all possible forms that may be used by all possible apps.
  • We could also do this as part of jlink, when creating a custom JDK image. However, some users may not want to create a new JDK image.
    • Also, there's currently no work-flow to include profiling data when building a custom JDK image (although this can be changed, probably as part of Project Leyden)
  • CDS dynamic dump can be used without generating profiling data in a separate step, so the usability is better.

CDS Design

We regenerate the XXX$Holder classes to contain all necessary methods used by the application.

Static Dump

During the trial run (with -XX:DumpLoadedClassList=classlist), we can save the list of LambdaForm handlers using a special syntax Overally, we want to modify lookupPregenerated() to something like:

Code Block
# regular   case xxxxxx: return resolveFrom(name, invokerType, directMethodHandleHolders);


Class[] directMethodHandleHolders = {
    DirectMethodHandle.Holder.class, // the one in jdk/lib/modules
    Class.forName("java/lang/invoke/DirectMethodHandle$CDSHolder1"), // if available, from CDS static archive
    Class.forName("java/lang/invoke/DirectMethodHandle$CDSHolder2"), // if available, from CDS static archive
};

During CDS dump (static or dynamic), we will generate the CDSHolder1 and CDSHolder2 classes according to the program's execution profile.

Static Dump

During the trial run (with -XX:DumpLoadedClassList=classlist), we can save the list of LambdaForm handlers using a special syntax like:

Code Block
# regular class specifier
java/lang/Object
# LambdaForm specifier (syntax TBD, but probably following the output of
# -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC L3I_I
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC LLI_I
....


#The output of  -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true (javac HelloWorld.java):
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L7_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LL_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L8_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder invokeExact_MT L8_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L3_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L4_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder getReference LL_L (success)
[LF_RESOLVE] java.lang.invoke.LambdaForm$Holder identity_L LL_L (success)
[LF_RESOLVE] java.lang.invoke.LambdaForm$Holder zero_L L_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LL_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L3_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial LL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L3_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod LL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual LL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeInterface L3_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LL_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LI_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L3_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L4_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L3_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L4_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L5_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L4_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L3_V (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L4IIL_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L4II_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L5II_L (fail)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L3IIL_L (fail)
[LF_RESOLVE] java.lang.invoke.DelegatingMethodHandle$Holder delegate L3_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L4_V (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual L3_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeInterface L3_V (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L6_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L7_L (success)
[LF_RESOLVE] java.lang.invoke.DelegatingMethodHandle$Holder delegate L6_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder invokeExact_MT L7_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LLJ_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L3J_L (success)
[LF_RESOLVE] java.lang.invoke.DelegatingMethodHandle$Holder reinvoke_L LLJ_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LJLIL_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLJLIL_J (success)
[LF_RESOLVE] java.lang.invoke.DelegatingMethodHandle$Holder reinvoke_L LJLIL_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L5_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLJLI_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LJ_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLJ_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LJI_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLJI_J (success)
[LF_RESOLVE] java.lang.invoke.DelegatingMethodHandle$Holder reinvoke_L LJI_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L4J_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder getLong LL_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLI_J (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLI_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod IL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC LLI_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStaticInit LL_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual LL_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStaticInit LL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L5_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L6_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L5_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial L6_L (fail)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod L6_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual L3_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeInterface LL_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStaticInit L_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LII_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial LI_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LI3_I (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder newInvokeSpecial LII_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial LLII_L (success)
[LF_RESOLVE] java.lang.invoke.Invokers$Holder linkToTargetMethod IIL_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual L3_V (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L4_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual L3II_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual LLI_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L3II_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L6_V (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L5_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LL_V (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LLII_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecial L3_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeInterface LL_L (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L_V (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic LI_L (success)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L4_I (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeVirtual LL_V (fail)
[LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic L3_V (fail)


total is 93.
But with LambdaForm only 2:
[LF_RESOLVE] java.lang.invoke.LambdaForm$Holder identity_L LL_L (success)
[LF_RESOLVE] java.lang.invoke.LambdaForm$Holder zero_L L_L (success)


# for LambdaForm:
# javac -J-verbose HelloWorld.java | grep grep LambdaForm | grep __JVM_LookupDefineClass__
# total is 36.

We collect all the LF_RESOLVE lines when parsing the classlist. At the end of the static dump, we invoke generateDirectMethodHandleHolderClassBytes to generate the DirectMethodHandle$CDSHolder1 class (as well as other holder classes that are currently generated by GenerateJLIClassesPlugin.java.)

Details TBD ....

Dynamic Dump

...

class specifier
java/lang/Object
# LambdaForm specifier
@lambda-form-invoker [LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC L3I_I
@lambda-form-invoker [SPECIES_RESOLVE] java.lang.invoke.SimpleMethodHandle

We collect all the @lambda-form-invoker lines when parsing the classlist. At the end of the static dump:

  • We invoke generateDirectMethodHandleHolderClassBytes to generate a customized version of DirectMethodHandle$Holder (as well as other holder classes that are currently generated by GenerateJLIClassesPlugin.java.)
    • This DirectMethodHandle$Holder class has all the methods needed for resolving the MethodHandle LambdaForms during the trial run.
    • Store the InstanceKlass of the customized version of DirectMethodHandle$Holder into the CDS archive.

Preliminary webrev:

  • http://cr.openjdk.java.net/~minqi/2020/8247536/webrev-01/
  • The generation of the customized DirectMethodHandle$Holder is done in MetaspaceShared::regenerate_holder_classes().

Dynamic Dump

  • (This will be done in a follow-up RFE)
  • Collect a @lambda-form-invoker list (in memory) when -XX:ArchiveClassesAtExit is specified.
  • When the dynamic archive is dumped, use this list to create customized Holder classes.
  • TBD



Overview
Content Tools
ThemeBuilder

Terms of Use
• License: GPLv2
• Privacy • Trademarks • Contact Us

Powered by a free Atlassian Confluence Open Source Project License granted to https://www.atlassian.com/software/views/opensource-community-additional-license-offer. Evaluate Confluence today.

  • Kolekti ThemeBuilder Powered by Atlassian Confluence 8.5.23
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 397, "requestCorrelationId": "023d4057e48d5b7d"}