5757import static java .lang .invoke .MethodHandleNatives .Constants .*;
5858import static java .lang .invoke .MethodHandleStatics .*;
5959import static java .lang .invoke .MethodHandles .Lookup .IMPL_LOOKUP ;
60+ import static jdk .internal .constant .ConstantUtils .concat ;
61+ import static jdk .internal .constant .ConstantUtils .validateInternalClassName ;
6062
6163/**
6264 * Code generation backend for LambdaForm.
@@ -67,6 +69,7 @@ class InvokerBytecodeGenerator {
6769 /** Define class names for convenience. */
6870 private static final ClassDesc CD_CasesHolder = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/MethodHandleImpl$CasesHolder;" );
6971 private static final ClassDesc CD_DirectMethodHandle = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/DirectMethodHandle;" );
72+ private static final ClassDesc CD_MemberName = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/MemberName;" );
7073 private static final ClassDesc CD_MethodHandleImpl = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/MethodHandleImpl;" );
7174 private static final ClassDesc CD_LambdaForm = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/LambdaForm;" );
7275 private static final ClassDesc CD_LambdaForm_Name = ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/LambdaForm$Name;" );
@@ -126,7 +129,8 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
126129 }
127130 this .name = name ;
128131 this .className = CLASS_PREFIX .concat (name );
129- this .classDesc = ClassDesc .ofInternalName (className );
132+ validateInternalClassName (name );
133+ this .classDesc = ReferenceClassDescImpl .ofValidated (concat ("L" , className , ";" ));
130134 this .lambdaForm = lambdaForm ;
131135 this .invokerName = invokerName ;
132136 this .invokerType = invokerType ;
@@ -142,8 +146,8 @@ private InvokerBytecodeGenerator(String name, String invokerName, MethodType inv
142146 // Create an array to map name indexes to locals indexes.
143147 localsMap [0 ] = 0 ; // localsMap has at least one element
144148 for (int i = 1 , index = 0 ; i < localsMap .length ; i ++) {
145- Wrapper w = Wrapper . forBasicType ( mt .parameterType (i - 1 ) );
146- index += w . stackSlots () ;
149+ Class <?> cl = mt .parameterType (i - 1 );
150+ index += ( cl == long . class || cl == double . class ) ? 2 : 1 ;
147151 localsMap [i ] = index ;
148152 }
149153 }
@@ -223,6 +227,7 @@ String classData(Object arg) {
223227
224228 // unique static variable name
225229 String name ;
230+ List <ClassData > classData = this .classData ;
226231 if (dumper ().isEnabled ()) {
227232 Class <?> c = arg .getClass ();
228233 while (c .isArray ()) {
@@ -232,8 +237,7 @@ String classData(Object arg) {
232237 } else {
233238 name = "_D_" + classData .size ();
234239 }
235- ClassData cd = new ClassData (name , desc , arg );
236- classData .add (cd );
240+ classData .add (new ClassData (name , desc , arg ));
237241 return name ;
238242 }
239243
@@ -292,15 +296,16 @@ private void methodSetup(ClassBuilder clb, Consumer<? super MethodBuilder> confi
292296 */
293297 private Object classDataValues () {
294298 final List <ClassData > cd = classData ;
295- return switch (cd .size ()) {
299+ int size = cd .size ();
300+ return switch (size ) {
296301 case 0 -> null ; // special case (classData is not used by <clinit>)
297302 case 1 -> cd .get (0 ).value ; // special case (single object)
298303 case 2 -> List .of (cd .get (0 ).value , cd .get (1 ).value );
299304 case 3 -> List .of (cd .get (0 ).value , cd .get (1 ).value , cd .get (2 ).value );
300305 case 4 -> List .of (cd .get (0 ).value , cd .get (1 ).value , cd .get (2 ).value , cd .get (3 ).value );
301306 default -> {
302- Object [] data = new Object [classData . size () ];
303- for (int i = 0 ; i < classData . size () ; i ++) {
307+ Object [] data = new Object [size ];
308+ for (int i = 0 ; i < size ; i ++) {
304309 data [i ] = classData .get (i ).value ;
305310 }
306311 yield List .of (data );
@@ -316,26 +321,28 @@ static void clinit(ClassBuilder clb, ClassDesc classDesc, List<ClassData> classD
316321 if (classData .isEmpty ())
317322 return ;
318323
319- for (ClassData p : classData ) {
320- // add the static field
321- clb .withField (p .name , p .desc , ACC_STATIC | ACC_FINAL );
322- }
323-
324324 clb .withMethodBody (CLASS_INIT_NAME , MTD_void , ACC_STATIC , new Consumer <>() {
325325 @ Override
326326 public void accept (CodeBuilder cob ) {
327327 cob .loadConstant (classDesc )
328328 .invokestatic (CD_MethodHandles , "classData" , MTD_Object_Class );
329- if (classData .size () == 1 ) {
329+ int size = classData .size ();
330+ if (size == 1 ) {
330331 ClassData p = classData .get (0 );
332+ // add the static field
333+ clb .withField (p .name , p .desc , ACC_STATIC | ACC_FINAL );
334+
331335 cob .checkcast (p .desc )
332336 .putstatic (classDesc , p .name , p .desc );
333337 } else {
334338 cob .checkcast (CD_List )
335339 .astore (0 );
336340 int index = 0 ;
337341 var listGet = cob .constantPool ().interfaceMethodRefEntry (CD_List , "get" , MTD_Object_int );
338- for (ClassData p : classData ) {
342+ for (int i = 0 ; i < size ; i ++) {
343+ ClassData p = classData .get (i );
344+ // add the static field
345+ clb .withField (p .name , p .desc , ACC_STATIC | ACC_FINAL );
339346 // initialize the static field
340347 cob .aload (0 )
341348 .loadConstant (index ++)
@@ -538,6 +545,11 @@ private boolean checkActualReceiver(CodeBuilder cob) {
538545 static final Annotation INJECTEDPROFILE = Annotation .of (ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/InjectedProfile;" ));
539546 static final Annotation LF_COMPILED = Annotation .of (ReferenceClassDescImpl .ofValidated ("Ljava/lang/invoke/LambdaForm$Compiled;" ));
540547
548+ // Suppress method in backtraces displayed to the user, mark this method as
549+ // a compiled LambdaForm, then either force or prohibit inlining.
550+ public static final RuntimeVisibleAnnotationsAttribute LF_DONTINLINE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute .of (HIDDEN , LF_COMPILED , DONTINLINE );
551+ public static final RuntimeVisibleAnnotationsAttribute LF_FORCEINLINE_ANNOTATIONS = RuntimeVisibleAnnotationsAttribute .of (HIDDEN , LF_COMPILED , FORCEINLINE );
552+
541553 /**
542554 * Generate an invoker method for the passed {@link LambdaForm}.
543555 */
@@ -558,21 +570,11 @@ void addMethod(ClassBuilder clb) {
558570 @ Override
559571 public void accept (MethodBuilder mb ) {
560572
561- List <Annotation > annotations = new ArrayList <>(3 );
562-
563- // Suppress this method in backtraces displayed to the user.
564- annotations .add (HIDDEN );
565-
566- // Mark this method as a compiled LambdaForm
567- annotations .add (LF_COMPILED );
568-
569573 if (lambdaForm .forceInline ) {
570- // Force inlining of this invoker method.
571- annotations .add (FORCEINLINE );
574+ mb .accept (LF_FORCEINLINE_ANNOTATIONS );
572575 } else {
573- annotations . add ( DONTINLINE );
576+ mb . accept ( LF_DONTINLINE_ANNOTATIONS );
574577 }
575- mb .accept (RuntimeVisibleAnnotationsAttribute .of (annotations ));
576578
577579 classData (lambdaForm ); // keep LambdaForm instance & its compiled form lifetime tightly coupled.
578580
@@ -1674,10 +1676,12 @@ public void accept(CodeBuilder cob) {
16741676
16751677 static ClassDesc classDesc (Class <?> cls ) {
16761678// assert(VerifyAccess.isTypeVisible(cls, Object.class)) : cls.getName();
1677- return cls .isPrimitive () ? Wrapper .forPrimitiveType (cls ).basicClassDescriptor ()
1678- : cls == MethodHandle .class ? CD_MethodHandle
1679+ return cls == MethodHandle .class ? CD_MethodHandle
16791680 : cls == DirectMethodHandle .class ? CD_DirectMethodHandle
16801681 : cls == Object .class ? CD_Object
1682+ : cls == MemberName .class ? CD_MemberName
1683+ : cls == MethodType .class ? CD_MethodType
1684+ : cls .isPrimitive () ? Wrapper .forPrimitiveType (cls ).basicClassDescriptor ()
16811685 : ReferenceClassDescImpl .ofValidated (cls .descriptorString ());
16821686 }
16831687
0 commit comments