3636import jdk .internal .vm .annotation .Stable ;
3737import sun .invoke .util .Wrapper ;
3838
39- import java .lang .classfile .Annotation ;
4039import java .lang .classfile .ClassBuilder ;
4140import java .lang .classfile .ClassFile ;
4241import java .lang .classfile .CodeBuilder ;
43- import java .lang .classfile .FieldBuilder ;
44- import java .lang .classfile .Label ;
4542import java .lang .classfile .TypeKind ;
46- import java .lang .classfile .attribute .RuntimeVisibleAnnotationsAttribute ;
4743import java .lang .constant .ClassDesc ;
4844import java .lang .constant .MethodTypeDesc ;
4945import java .lang .invoke .MethodHandles .Lookup ;
@@ -1076,6 +1072,7 @@ private static final class SimpleStringBuilderStrategy {
10761072 static final ClassFileDumper DUMPER =
10771073 ClassFileDumper .getInstance ("java.lang.invoke.StringConcatFactory.dump" , "stringConcatClasses" );
10781074 static final ClassDesc CD_StringConcatHelper = ClassDesc .ofDescriptor ("Ljava/lang/StringConcatHelper;" );
1075+ static final ClassDesc CD_StringConcatBase = ClassDesc .ofDescriptor ("Ljava/lang/StringConcatHelper$StringConcatBase;" );
10791076 static final ClassDesc CD_Array_byte = ClassDesc .ofDescriptor ("[B" );
10801077 static final ClassDesc CD_Array_String = ClassDesc .ofDescriptor ("[Ljava/lang/String;" );
10811078 static final MethodTypeDesc ARRAY_STRING_TO_VOID = MethodTypeDesc .of (CD_void , CD_Array_String );
@@ -1086,9 +1083,7 @@ private static final class SimpleStringBuilderStrategy {
10861083 static final MethodTypeDesc NEW_ARRAY_SUFFIX = MethodTypeDesc .of (CD_Array_byte , CD_String , CD_long );
10871084 static final MethodTypeDesc NEW_STRING = MethodTypeDesc .of (CD_String , CD_Array_byte , CD_long );
10881085
1089- static final MethodTypeDesc MTD_Object = MethodTypeDesc .of (CD_Object );
10901086 static final MethodTypeDesc MTD_int = MethodTypeDesc .of (CD_int );
1091- static final MethodTypeDesc MTD_byte = MethodTypeDesc .of (CD_byte );
10921087
10931088 static final MethodTypeDesc MIX_int = MethodTypeDesc .of (CD_long , CD_long , CD_int );
10941089 static final MethodTypeDesc MIX_long = MethodTypeDesc .of (CD_long , CD_long , CD_long );
@@ -1102,13 +1097,15 @@ private static final class SimpleStringBuilderStrategy {
11021097 static final MethodTypeDesc PREPEND_char = MethodTypeDesc .of (CD_long , CD_long , CD_Array_byte , CD_char , CD_String );
11031098 static final MethodTypeDesc PREPEND_String = MethodTypeDesc .of (CD_long , CD_long , CD_Array_byte , CD_String , CD_String );
11041099
1105- public static final RuntimeVisibleAnnotationsAttribute STABLE_ANNOTATION = RuntimeVisibleAnnotationsAttribute .of (
1106- Annotation .of (ClassDesc .ofDescriptor ("Ljdk/internal/vm/annotation/Stable;" )));
1107-
1108- private static final Consumer <FieldBuilder > FINAL_STABLE_FIELD = new Consumer <FieldBuilder >() {
1109- public void accept (FieldBuilder fb ) {
1110- fb .withFlags (ClassFile .ACC_FINAL )
1111- .with (STABLE_ANNOTATION );
1100+ private static final Consumer <CodeBuilder > CONSTRUCTOR_BUILDER = new Consumer <CodeBuilder >() {
1101+ @ Override
1102+ public void accept (CodeBuilder cb ) {
1103+ int thisSlot = cb .receiverSlot ();
1104+ int constantsSlot = cb .parameterSlot (0 );
1105+ cb .aload (thisSlot );
1106+ cb .aload (constantsSlot );
1107+ cb .invokespecial (CD_StringConcatBase , INIT_NAME , ARRAY_STRING_TO_VOID , false );
1108+ cb .return_ ();
11121109 }
11131110 };
11141111
@@ -1158,14 +1155,12 @@ private static MethodHandle generate(Lookup lookup, MethodType args, String[] co
11581155 new Consumer <ClassBuilder >() {
11591156 @ Override
11601157 public void accept (ClassBuilder clb ) {
1161- clb .withFlags (ClassFile .ACC_FINAL | ClassFile .ACC_SUPER | ClassFile .ACC_SYNTHETIC )
1162- .withField (LENGTH , CD_int , FINAL_STABLE_FIELD )
1163- .withField (CODER , CD_byte , FINAL_STABLE_FIELD )
1164- .withField (CONSTANTS , CD_Array_String , FINAL_STABLE_FIELD )
1158+ clb .withSuperclass (CD_StringConcatBase )
1159+ .withFlags (ClassFile .ACC_FINAL | ClassFile .ACC_SUPER | ClassFile .ACC_SYNTHETIC )
11651160 .withMethodBody ("<init>" ,
11661161 ARRAY_STRING_TO_VOID ,
11671162 ClassFile .ACC_PRIVATE ,
1168- generateConstructor ( concatClass , constants . length )
1163+ CONSTRUCTOR_BUILDER
11691164 )
11701165 .withMethodBody (METHOD_NAME ,
11711166 ConstantUtils .methodTypeDesc (concatArgs ),
@@ -1186,55 +1181,6 @@ public void accept(ClassBuilder clb) {
11861181 }
11871182 }
11881183
1189- private static Consumer <CodeBuilder > generateConstructor (ClassDesc concatClass , int numConstants ) {
1190- return new Consumer <CodeBuilder >() {
1191- @ Override
1192- public void accept (CodeBuilder cb ) {
1193- cb .aload (0 );
1194- cb .invokespecial (CD_Object , INIT_NAME , MTD_void , false );
1195- cb .aload (0 );
1196- cb .aload (1 );
1197- cb .putfield (concatClass , CONSTANTS , CD_Array_String );
1198- cb .iconst_0 ();
1199- cb .istore (2 );
1200- cb .iconst_0 ();
1201- cb .istore (3 );
1202- cb .iconst_0 ();
1203- cb .istore (4 );
1204- Label loopStart = cb .newLabel ();
1205- Label loopEnd = cb .newLabel ();
1206- {
1207- cb .labelBinding (loopStart );
1208- cb .iload (4 );
1209- cb .ldc (numConstants );
1210- cb .if_icmpge (loopEnd );
1211- cb .aload (1 );
1212- cb .iload (4 );
1213- cb .aaload ();
1214- cb .dup ();
1215- cb .invokevirtual (CD_String , LENGTH , MTD_int );
1216- cb .iload (2 );
1217- cb .iadd ();
1218- cb .istore (2 );
1219- cb .invokevirtual (CD_String , CODER , MTD_byte );
1220- cb .iload (3 );
1221- cb .ior ();
1222- cb .istore (3 );
1223- cb .iinc (4 , 1 );
1224- cb .goto_ (loopStart );
1225- }
1226- cb .labelBinding (loopEnd );
1227- cb .aload (0 );
1228- cb .iload (2 );
1229- cb .putfield (concatClass , LENGTH , CD_int );
1230- cb .aload (0 );
1231- cb .iload (3 );
1232- cb .putfield (concatClass , CODER , CD_byte );
1233- cb .return_ ();
1234- }
1235- };
1236- }
1237-
12381184 /**
12391185 * Generate InlineCopy-based code. <p>
12401186 *
0 commit comments