7979import org .eclipse .jdt .internal .compiler .ast .SingleMemberAnnotation ;
8080import org .eclipse .jdt .internal .compiler .ast .SingleNameReference ;
8181import org .eclipse .jdt .internal .compiler .ast .StringLiteral ;
82+ import org .eclipse .jdt .internal .compiler .ast .StringTemplate ;
8283import org .eclipse .jdt .internal .compiler .ast .SwitchStatement ;
8384import org .eclipse .jdt .internal .compiler .ast .TypeDeclaration ;
8485import org .eclipse .jdt .internal .compiler .ast .TypeParameter ;
@@ -201,9 +202,10 @@ public class ClassFile implements TypeConstants, TypeIds {
201202 public static final String ENUMDESC_OF = "EnumDesc.of" ; //$NON-NLS-1$
202203 public static final String CLASSDESC = "ClassDesc" ; //$NON-NLS-1$
203204 public static final String CLASSDESC_OF = "ClassDesc.of" ; //$NON-NLS-1$
205+ public static final String PROCESS_STRING = "process" ; //$NON-NLS-1$
206+ public static final String NEW_STRING_TEMPLATE = "newStringTemplate" ; //$NON-NLS-1$
204207 public static final String [] BOOTSTRAP_METHODS = { ALTMETAFACTORY_STRING , METAFACTORY_STRING , BOOTSTRAP_STRING ,
205- TYPESWITCH_STRING , ENUMSWITCH_STRING , CONCAT_CONSTANTS , INVOKE_STRING , ENUMDESC_OF , CLASSDESC , CLASSDESC_OF };
206-
208+ TYPESWITCH_STRING , ENUMSWITCH_STRING , CONCAT_CONSTANTS , INVOKE_STRING , ENUMDESC_OF , CLASSDESC , CLASSDESC_OF , PROCESS_STRING , NEW_STRING_TEMPLATE };
207209 /**
208210 * INTERNAL USE-ONLY
209211 * Request the creation of a ClassFile compatible representation of a problematic type
@@ -619,7 +621,7 @@ private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffs
619621 int size = allTypeAnnotationContexts .size ();
620622 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
621623 null ,
622- ( node ) -> size > 0 ,
624+ node -> size > 0 ,
623625 () -> allTypeAnnotationContexts );
624626 }
625627 } finally {
@@ -672,7 +674,7 @@ private int addComponentAttributes(RecordComponentBinding recordComponentBinding
672674 int size = allTypeAnnotationContexts .size ();
673675 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
674676 null ,
675- ( node ) -> size > 0 ,
677+ node -> size > 0 ,
676678 () -> allTypeAnnotationContexts );
677679
678680 }
@@ -1761,7 +1763,7 @@ public int generateTypeAnnotationsOnCodeAttribute() {
17611763 int size = allTypeAnnotationContexts .size ();
17621764 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
17631765 null ,
1764- ( node ) -> size > 0 ,
1766+ node -> size > 0 ,
17651767 () -> allTypeAnnotationContexts );
17661768 return attributesNumber ;
17671769 }
@@ -2473,7 +2475,7 @@ public void completeMethodInfo(
24732475 int size = allTypeAnnotationContexts .size ();
24742476 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
24752477 null ,
2476- ( node ) -> size > 0 ,
2478+ node -> size > 0 ,
24772479 () -> allTypeAnnotationContexts );
24782480 }
24792481 if ((this .produceAttributes & ClassFileConstants .ATTR_METHOD_PARAMETERS ) != 0 ||
@@ -3667,6 +3669,8 @@ private int generateBootstrapMethods(List<Object> bootStrapMethodsList) {
36673669 localContentsOffset = addBootStrapTypeCaseConstantEntry (localContentsOffset , (ResolvedCase ) o , fPtr );
36683670 } else if (o instanceof TypeBinding ) {
36693671 localContentsOffset = addClassDescBootstrap (localContentsOffset , (TypeBinding ) o , fPtr );
3672+ } else if (o instanceof StringTemplate template ) {
3673+ localContentsOffset = addBootStrapTemplateRuntimeEntry (localContentsOffset , template , fPtr );
36703674 }
36713675 }
36723676
@@ -3836,7 +3840,7 @@ private int addBootStrapRecordEntry(int localContentsOffset, TypeDeclaration typ
38363840 String names =
38373841 Arrays .stream (recordComponents )
38383842 .map (f -> new String (f .name ))
3839- .reduce ((s1 , s2 ) -> { return s1 + ";" + s2 ;} ) //$NON-NLS-1$
3843+ .reduce ((s1 , s2 ) -> ( s1 + ";" + s2 ) ) //$NON-NLS-1$
38403844 .orElse (Util .EMPTY_STRING );
38413845 int namesIndex = this .constantPool .literalIndex (names );
38423846 this .contents [localContentsOffset ++] = (byte ) (namesIndex >> 8 );
@@ -4021,6 +4025,7 @@ private int addBootStrapEnumSwitchEntry(int localContentsOffset, SwitchStatement
40214025 int numArgsLocation = localContentsOffset ;
40224026 CaseStatement .ResolvedCase [] constants = switchStatement .otherConstants ;
40234027 int numArgs = constants .length ;
4028+ if (switchStatement .containsNull ) --numArgs ;
40244029 this .contents [numArgsLocation ++] = (byte ) (numArgs >> 8 );
40254030 this .contents [numArgsLocation ] = (byte ) numArgs ;
40264031 localContentsOffset += 2 ;
@@ -4032,8 +4037,11 @@ private int addBootStrapEnumSwitchEntry(int localContentsOffset, SwitchStatement
40324037 this .contents [localContentsOffset ++] = (byte ) (typeIndex >> 8 );
40334038 this .contents [localContentsOffset ++] = (byte ) typeIndex ;
40344039 } else {
4040+ if (c .e instanceof NullLiteral ) continue ;
4041+ String s = c .e instanceof QualifiedNameReference qnr ? // handle superfluously qualified enumerator.
4042+ new String (qnr .tokens [qnr .tokens .length -1 ]) : c .e .toString ();
40354043 int intValIdx =
4036- this .constantPool .literalIndex (c . e . toString () );
4044+ this .constantPool .literalIndex (s );
40374045 this .contents [localContentsOffset ++] = (byte ) (intValIdx >> 8 );
40384046 this .contents [localContentsOffset ++] = (byte ) intValIdx ;
40394047 }
@@ -4067,6 +4075,40 @@ private int addBootStrapStringConcatEntry(int localContentsOffset, String recipe
40674075
40684076 return localContentsOffset ;
40694077 }
4078+ private int addBootStrapTemplateRuntimeEntry (int localContentsOffset , StringTemplate template , Map <String , Integer > fPtr ) {
4079+ final int contentsEntries = 10 ;
4080+ int indexForProcess = fPtr .get (NEW_STRING_TEMPLATE );
4081+ if (contentsEntries + localContentsOffset >= this .contents .length ) {
4082+ resizeContents (contentsEntries );
4083+ }
4084+ if (indexForProcess == 0 ) {
4085+ ReferenceBinding javaLangRuntimeTemplateBootstraps = this .referenceBinding .scope .getJavaLangRuntimeTemplateRuntimeBootstraps ();
4086+ indexForProcess = this .constantPool .literalIndexForMethodHandle (ClassFileConstants .MethodHandleRefKindInvokeStatic , javaLangRuntimeTemplateBootstraps ,
4087+ NEW_STRING_TEMPLATE .toCharArray (), ConstantPool .JAVA_LANG_RUNTIME_STRING_TEMPLATE_SIGNATURE , false );
4088+ fPtr .put (NEW_STRING_TEMPLATE , indexForProcess );
4089+ }
4090+ this .contents [localContentsOffset ++] = (byte ) (indexForProcess >> 8 );
4091+ this .contents [localContentsOffset ++] = (byte ) indexForProcess ;
4092+
4093+ // u2 num_bootstrap_arguments
4094+ int numArgsLocation = localContentsOffset ;
4095+ StringLiteral [] fragments = template .fragments ();
4096+ int numArgs = fragments .length ;
4097+ this .contents [numArgsLocation ++] = (byte ) (numArgs >> 8 );
4098+ this .contents [numArgsLocation ] = (byte ) numArgs ;
4099+ localContentsOffset += 2 ;
4100+
4101+ if ((numArgs * 2 ) + localContentsOffset >= this .contents .length ) {
4102+ resizeContents (numArgs * 2 );
4103+ }
4104+ for (StringLiteral frag : fragments ) {
4105+ int intValIdx =
4106+ this .constantPool .literalIndex (frag .constant .stringValue ());
4107+ this .contents [localContentsOffset ++] = (byte ) (intValIdx >> 8 );
4108+ this .contents [localContentsOffset ++] = (byte ) intValIdx ;
4109+ }
4110+ return localContentsOffset ;
4111+ }
40704112 private int generateLineNumberAttribute () {
40714113 int localContentsOffset = this .contentsOffset ;
40724114 int attributesNumber = 0 ;
@@ -4399,7 +4441,7 @@ public int generateMethodInfoAttributes(MethodBinding methodBinding) {
43994441 int size = allTypeAnnotationContexts .size ();
44004442 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
44014443 null ,
4402- ( node ) -> size > 0 ,
4444+ node -> size > 0 ,
44034445 () -> allTypeAnnotationContexts );
44044446 }
44054447 }
@@ -4585,7 +4627,7 @@ public void addSyntheticDeserializeLambda(SyntheticMethodBinding methodBinding,
45854627 * That method generates the method info header of a clinit:
45864628 * The header consists in:
45874629 * - the access flags (always default access + static)
4588- * - the name index of the method name (always <clinit>) inside the constant pool
4630+ * - the name index of the method name (always {@code <clinit>} ) inside the constant pool
45894631 * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
45904632 */
45914633 public void generateMethodInfoHeaderForClinit () {
@@ -5137,7 +5179,10 @@ private int generateMethodParameters(final MethodBinding binding) {
51375179 for (int i = 0 , max = targetParameters .length , argumentsLength = arguments != null ? arguments .length : 0 ; i < max ; i ++) {
51385180 if (argumentsLength > i && arguments [i ] != null ) {
51395181 Argument argument = arguments [i ];
5140- length = writeArgumentName (argument .name , argument .binding .modifiers , length );
5182+ int modifiers = argument .binding .modifiers ;
5183+ if (binding .isCompactConstructor ())
5184+ modifiers |= ClassFileConstants .AccMandated ;
5185+ length = writeArgumentName (argument .name , modifiers , length );
51415186 } else {
51425187 length = writeArgumentName (null , ClassFileConstants .AccSynthetic , length );
51435188 }
@@ -5850,7 +5895,7 @@ private int generateTypeAnnotationAttributeForTypeDeclaration() {
58505895 int size = allTypeAnnotationContexts .size ();
58515896 attributesNumber = completeRuntimeTypeAnnotations (attributesNumber ,
58525897 null ,
5853- ( node ) -> size > 0 ,
5898+ node -> size > 0 ,
58545899 () -> allTypeAnnotationContexts );
58555900 return attributesNumber ;
58565901 }
@@ -6394,6 +6439,13 @@ public int recordBootstrapMethod(String expression) {
63946439 this .bootstrapMethods .add (expression );
63956440 return this .bootstrapMethods .size () - 1 ;
63966441 }
6442+ public int recordBootstrapMethod (StringTemplate template ) {
6443+ if (this .bootstrapMethods == null ) {
6444+ this .bootstrapMethods = new ArrayList <>();
6445+ }
6446+ this .bootstrapMethods .add (template );
6447+ return this .bootstrapMethods .size () - 1 ;
6448+ }
63976449 public void reset (/*@Nullable*/ SourceTypeBinding typeBinding , CompilerOptions options ) {
63986450 // the code stream is reinitialized for each method
63996451 if (typeBinding != null ) {
@@ -6530,7 +6582,7 @@ public int compare(StackMapFrame frame, StackMapFrame frame2) {
65306582 }
65316583
65326584 private TypeBinding getTypeBinding (char [] typeConstantPoolName , Scope scope , boolean checkcast ) {
6533- if (typeConstantPoolName .length == 1 ) {
6585+ if (typeConstantPoolName .length == 1 && ! checkcast ) {
65346586 // base type
65356587 switch (typeConstantPoolName [0 ]) {
65366588 case 'Z' :
@@ -6828,6 +6880,7 @@ public List<StackMapFrame> traverse(
68286880 }
68296881 }
68306882 byte opcode = (byte ) u1At (bytecodes , 0 , pc );
6883+ inspectFrame (currentPC , frame );
68316884 switch (opcode ) {
68326885 case Opcodes .OPC_nop :
68336886 pc ++;
@@ -7811,6 +7864,10 @@ public List<StackMapFrame> traverse(
78117864 return filterFakeFrames (realJumpTarget , frames , codeLength );
78127865 }
78137866
7867+ private void inspectFrame (int currentPC , StackMapFrame frame ) {
7868+ // Plant a breakpoint at the call site to conveniently hover.
7869+ }
7870+
78147871 private StackMapFrame createNewFrame (int currentPC , StackMapFrame frame , boolean isClinit , MethodBinding methodBinding ) {
78157872 StackMapFrame newFrame = frame .duplicate ();
78167873 newFrame .pc = currentPC ;
0 commit comments