3939import java .util .ArrayList ;
4040import java .util .HashMap ;
4141import java .util .List ;
42+ import java .util .Map ;
4243
4344import jdk .vm .ci .common .JVMCIError ;
4445import jdk .vm .ci .meta .Assumptions .AssumptionResult ;
5051import jdk .vm .ci .meta .JavaConstant ;
5152import jdk .vm .ci .meta .JavaKind ;
5253import jdk .vm .ci .meta .JavaType ;
54+ import jdk .vm .ci .meta .MetaUtil ;
5355import jdk .vm .ci .meta .ResolvedJavaField ;
5456import jdk .vm .ci .meta .ResolvedJavaMethod ;
5557import jdk .vm .ci .meta .ResolvedJavaRecordComponent ;
@@ -744,6 +746,51 @@ protected HotSpotResolvedObjectTypeImpl getArrayType() {
744746 return runtime ().compilerToVm .getArrayType ((char ) 0 , this );
745747 }
746748
749+ /**
750+ * Map to mitigate exponential cost of {@link #lookupField} for classes with many fields.
751+ */
752+ Map <FieldInfo .Key , Integer > fieldInfoMap ;
753+
754+ /**
755+ * Classes with more than this number of fields will use {@link #fieldInfoMap}
756+ * in {@link #lookupField(Field)}.
757+ */
758+ private static final int FIELD_INFO_MAP_THRESHOLD = 1024 ;
759+
760+ /**
761+ * Support for {@link HotSpotMetaAccessProvider#lookupJavaField(Field)}.
762+ */
763+ HotSpotResolvedJavaField lookupField (Field reflectionField ) {
764+ FieldInfo [] fields = getFieldInfo ();
765+ String name = reflectionField .getName ();
766+ String sig = MetaUtil .toInternalName (reflectionField .getType ().getName ());
767+ boolean isStatic = Modifier .isStatic (reflectionField .getModifiers ());
768+ FieldInfo .Key key = new FieldInfo .Key (name , sig , isStatic );
769+ if (fields .length > FIELD_INFO_MAP_THRESHOLD ) {
770+ if (fieldInfoMap == null ) {
771+ Map <FieldInfo .Key , Integer > map = new HashMap <>(fields .length );
772+ for (int index = 0 ; index < fields .length ; index ++) {
773+ FieldInfo fi = fields [index ];
774+ map .put (FieldInfo .Key .from (fi , this ), index );
775+ }
776+ fieldInfoMap = map ;
777+ }
778+ Integer index = fieldInfoMap .get (key );
779+ if (index != null ) {
780+ FieldInfo fi = fields [index ];
781+ return createField (fi .getType (this ), fi .offset (), fi .classfileFlags (), fi .internalFlags (), index );
782+ }
783+ } else {
784+ for (int index = 0 ; index < fields .length ; index ++) {
785+ FieldInfo fi = fields [index ];
786+ if (FieldInfo .Key .from (fi , this ).equals (key )) {
787+ return createField (fi .getType (this ), fi .offset (), fi .classfileFlags (), fi .internalFlags (), index );
788+ }
789+ }
790+ }
791+ throw new JVMCIError ("unresolved field %s" , reflectionField );
792+ }
793+
747794 /**
748795 * This class represents the field information for one field contained in the fields array of an
749796 * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
@@ -755,8 +802,18 @@ protected HotSpotResolvedObjectTypeImpl getArrayType() {
755802 * @param internalFlags field's internal flags (from the VM)
756803 * @param initializerIndex field's initial value index in the constant pool
757804 */
758- record FieldInfo (int nameIndex , int signatureIndex , int offset , int classfileFlags , int internalFlags ,
759- int initializerIndex ) {
805+ record FieldInfo (int nameIndex ,
806+ int signatureIndex ,
807+ int offset ,
808+ int classfileFlags ,
809+ int internalFlags ,
810+ int initializerIndex ) {
811+
812+ record Key (String name , String signature , boolean isStatic ) {
813+ static Key from (FieldInfo fi , HotSpotResolvedObjectTypeImpl holder ) {
814+ return new FieldInfo .Key (fi .getName (holder ), fi .getSignature (holder ), fi .isStatic ());
815+ }
816+ }
760817
761818 /**
762819 * Returns the name of this field as a {@link String}. If the field is an internal field the
@@ -880,8 +937,9 @@ private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSp
880937 int resultCount = 0 ;
881938 int index ;
882939
883- for (index = 0 ; index < getFieldInfo ().length ; index ++) {
884- if (getFieldInfo (index ).isStatic () == retrieveStaticFields ) {
940+ FieldInfo [] fieldInfo = getFieldInfo ();
941+ for (index = 0 ; index < fieldInfo .length ; index ++) {
942+ if (fieldInfo [index ].isStatic () == retrieveStaticFields ) {
885943 resultCount ++;
886944 }
887945 }
@@ -902,8 +960,8 @@ private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSp
902960 // but the array of fields to be returned must be sorted by increasing offset
903961 // This code populates the array, then applies the sorting function
904962 int resultIndex = prependLength ;
905- for (int i = 0 ; i < getFieldInfo () .length ; ++i ) {
906- FieldInfo field = getFieldInfo ( i ) ;
963+ for (int i = 0 ; i < fieldInfo .length ; ++i ) {
964+ FieldInfo field = fieldInfo [ i ] ;
907965 if (field .isStatic () == retrieveStaticFields ) {
908966 int offset = field .offset ();
909967 HotSpotResolvedJavaField resolvedJavaField = createField (field .getType (this ), offset , field .classfileFlags (), field .internalFlags (), i );
@@ -1058,7 +1116,7 @@ private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expec
10581116 // @formatter:off
10591117 if (ByteOrder .nativeOrder () == ByteOrder .BIG_ENDIAN &&
10601118 expectedEntryKind .isPrimitive () &&
1061- !expectedEntryKind .equals (JavaKind .Void ) &&
1119+ !expectedEntryKind .equals (jdk . vm . ci . meta . JavaKind .Void ) &&
10621120 field .getJavaKind ().isPrimitive ()) {
10631121 resolvedFieldOffset +=
10641122 field .getJavaKind ().getByteCount () -
0 commit comments