Skip to content

Commit 0cb110e

Browse files
author
Doug Simon
committed
8350892: [JVMCI] Align ResolvedJavaType.getInstanceFields with Class.getDeclaredFields
Reviewed-by: yzheng, never, thartmann
1 parent 04eac0c commit 0cb110e

File tree

6 files changed

+57
-71
lines changed

6 files changed

+57
-71
lines changed

src/hotspot/share/ci/ciInstanceKlass.cpp

-11
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,6 @@ ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static)
400400
int field_off = field->offset_in_bytes();
401401
if (field_off == field_offset)
402402
return field;
403-
if (field_off > field_offset)
404-
break;
405-
// could do binary search or check bins, but probably not worth it
406403
}
407404
return nullptr;
408405
}
@@ -431,11 +428,6 @@ ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature,
431428
}
432429

433430

434-
static int sort_field_by_offset(ciField** a, ciField** b) {
435-
return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
436-
// (no worries about 32-bit overflow...)
437-
}
438-
439431
// ------------------------------------------------------------------
440432
// ciInstanceKlass::compute_nonstatic_fields
441433
int ciInstanceKlass::compute_nonstatic_fields() {
@@ -476,9 +468,6 @@ int ciInstanceKlass::compute_nonstatic_fields() {
476468

477469
int flen = fields->length();
478470

479-
// Now sort them by offset, ascending.
480-
// (In principle, they could mix with superclass fields.)
481-
fields->sort(sort_field_by_offset);
482471
_nonstatic_fields = fields;
483472
return flen;
484473
}

src/hotspot/share/ci/ciInstanceKlass.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class ciInstanceKlass : public ciKlass {
6767
ciInstance* _java_mirror;
6868

6969
ciConstantPoolCache* _field_cache; // cached map index->field
70-
GrowableArray<ciField*>* _nonstatic_fields;
70+
GrowableArray<ciField*>* _nonstatic_fields; // ordered by JavaFieldStream
7171
int _has_injected_fields; // any non static injected fields? lazily initialized.
7272

7373
// The possible values of the _implementor fall into following three cases:

src/hotspot/share/runtime/deoptimization.cpp

+23-23
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,9 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, nmethod* co
377377
realloc_failures = Deoptimization::realloc_objects(thread, &deoptee, &map, objects, THREAD);
378378
JRT_END
379379
}
380-
bool skip_internal = (compiled_method != nullptr) && !compiled_method->is_compiled_by_jvmci();
381-
Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
380+
guarantee(compiled_method != nullptr, "deopt must be associated with an nmethod");
381+
bool is_jvmci = compiled_method->is_compiled_by_jvmci();
382+
Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, is_jvmci);
382383
if (TraceDeoptimization) {
383384
print_objects(deoptee_thread, objects, realloc_failures);
384385
}
@@ -1458,27 +1459,26 @@ class ReassignedField {
14581459
}
14591460
};
14601461

1461-
static int compare(ReassignedField* left, ReassignedField* right) {
1462-
return left->_offset - right->_offset;
1463-
}
1464-
1465-
// Restore fields of an eliminated instance object using the same field order
1466-
// returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true)
1467-
static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal) {
1468-
GrowableArray<ReassignedField>* fields = new GrowableArray<ReassignedField>();
1469-
InstanceKlass* ik = klass;
1470-
while (ik != nullptr) {
1471-
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
1472-
if (!fs.access_flags().is_static() && (!skip_internal || !fs.field_flags().is_injected())) {
1473-
ReassignedField field;
1474-
field._offset = fs.offset();
1475-
field._type = Signature::basic_type(fs.signature());
1476-
fields->append(field);
1477-
}
1462+
// Gets the fields of `klass` that are eliminated by escape analysis and need to be reassigned
1463+
static GrowableArray<ReassignedField>* get_reassigned_fields(InstanceKlass* klass, GrowableArray<ReassignedField>* fields, bool is_jvmci) {
1464+
InstanceKlass* super = klass->superklass();
1465+
if (super != nullptr) {
1466+
get_reassigned_fields(super, fields, is_jvmci);
1467+
}
1468+
for (AllFieldStream fs(klass); !fs.done(); fs.next()) {
1469+
if (!fs.access_flags().is_static() && (is_jvmci || !fs.field_flags().is_injected())) {
1470+
ReassignedField field;
1471+
field._offset = fs.offset();
1472+
field._type = Signature::basic_type(fs.signature());
1473+
fields->append(field);
14781474
}
1479-
ik = ik->superklass();
14801475
}
1481-
fields->sort(compare);
1476+
return fields;
1477+
}
1478+
1479+
// Restore fields of an eliminated instance object employing the same field order used by the compiler.
1480+
static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool is_jvmci) {
1481+
GrowableArray<ReassignedField>* fields = get_reassigned_fields(klass, new GrowableArray<ReassignedField>(), is_jvmci);
14821482
for (int i = 0; i < fields->length(); i++) {
14831483
ScopeValue* scope_field = sv->field_at(svIndex);
14841484
StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field);
@@ -1560,7 +1560,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
15601560
}
15611561

15621562
// restore fields of all eliminated objects and arrays
1563-
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal) {
1563+
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool is_jvmci) {
15641564
for (int i = 0; i < objects->length(); i++) {
15651565
assert(objects->at(i)->is_object(), "invalid debug information");
15661566
ObjectValue* sv = (ObjectValue*) objects->at(i);
@@ -1604,7 +1604,7 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
16041604
}
16051605
if (k->is_instance_klass()) {
16061606
InstanceKlass* ik = InstanceKlass::cast(k);
1607-
reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
1607+
reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), is_jvmci);
16081608
} else if (k->is_typeArray_klass()) {
16091609
TypeArrayKlass* ak = TypeArrayKlass::cast(k);
16101610
reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java

-9
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
6767

6868
private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
6969
private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
70-
private static final SortByOffset fieldSortingMethod = new SortByOffset();
7170

7271
/**
7372
* The {@code Klass*} of this type.
@@ -782,12 +781,6 @@ public boolean isStatic() {
782781
}
783782
}
784783

785-
static class SortByOffset implements Comparator<ResolvedJavaField> {
786-
public int compare(ResolvedJavaField a, ResolvedJavaField b) {
787-
return a.getOffset() - b.getOffset();
788-
}
789-
}
790-
791784
@Override
792785
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
793786
if (instanceFields == null) {
@@ -817,7 +810,6 @@ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
817810
result[i++] = f;
818811
}
819812
}
820-
Arrays.sort(result, fieldSortingMethod);
821813
return result;
822814
} else {
823815
// The super classes of this class do not have any instance fields.
@@ -876,7 +868,6 @@ private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSp
876868
result[resultIndex++] = resolvedJavaField;
877869
}
878870
}
879-
Arrays.sort(result, fieldSortingMethod);
880871
return result;
881872
}
882873

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -284,24 +284,21 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso
284284
AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
285285

286286
/**
287-
* Returns the instance fields of this class, including
287+
* Returns the non-static fields of this class, including
288288
* {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
289-
* for array and primitive types. The order of fields returned by this method is stable. That
290-
* is, for a single JVM execution the same order is returned each time this method is called. It
291-
* is also the "natural" order, which means that the JVM would expect the fields in this order
292-
* if no specific order is given.
289+
* for array and primitive types. The order of fields declared by a single class returned by
290+
* this method is the same as {@link Class#getDeclaredFields}.
293291
*
294-
* @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
295-
* type are included in the result
296-
* @return an array of instance fields
292+
* @param includeSuperclasses if true, then non-static fields for the complete hierarchy of this
293+
* type are included in the result with superclass fields coming before subclass fields
294+
* @return an array of non-static fields
297295
*/
298296
ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses);
299297

300298
/**
301299
* Returns the static fields of this class, including {@linkplain ResolvedJavaField#isInternal()
302300
* internal} fields. A zero-length array is returned for array and primitive types. The order of
303-
* fields returned by this method is stable. That is, for a single JVM execution the same order
304-
* is returned each time this method is called.
301+
* fields returned by this method is the same as {@link Class#getDeclaredFields}.
305302
*/
306303
ResolvedJavaField[] getStaticFields();
307304

test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java

+26-17
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@
7171
import java.lang.reflect.Field;
7272
import java.lang.reflect.Method;
7373
import java.lang.reflect.Modifier;
74+
import java.util.ArrayList;
7475
import java.util.Arrays;
76+
import java.util.Collection;
7577
import java.util.Collections;
7678
import java.util.function.BiConsumer;
7779
import java.util.function.Supplier;
@@ -144,7 +146,7 @@ private static Class<? extends Annotation> findPolymorphicSignatureClass() {
144146
public void findInstanceFieldWithOffsetTest() {
145147
for (Class<?> c : classes) {
146148
ResolvedJavaType type = metaAccess.lookupJavaType(c);
147-
Set<Field> reflectionFields = getInstanceFields(c, true);
149+
Set<Field> reflectionFields = Set.copyOf(getInstanceFields(c, true));
148150
for (Field f : reflectionFields) {
149151
ResolvedJavaField rf = lookupField(type.getInstanceFields(true), f);
150152
assertNotNull(rf);
@@ -872,18 +874,20 @@ public void findUniqueConcreteMethodTest() throws NoSuchMethodException {
872874
assertEquals(thisMethod, ucm);
873875
}
874876

875-
public static Set<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
877+
public static List<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
876878
if (c.isArray() || c.isPrimitive() || c.isInterface()) {
877-
return Collections.emptySet();
879+
return List.of();
878880
}
879-
Set<Field> result = new HashSet<>();
881+
List<Field> result = new ArrayList<>();
880882
for (Field f : c.getDeclaredFields()) {
881883
if (!Modifier.isStatic(f.getModifiers())) {
882884
result.add(f);
883885
}
884886
}
885887
if (includeSuperclasses && c != Object.class) {
886-
result.addAll(getInstanceFields(c.getSuperclass(), true));
888+
List<Field> allFields = getInstanceFields(c.getSuperclass(), true);
889+
allFields.addAll(result);
890+
result = allFields;
887891
}
888892
return result;
889893
}
@@ -912,7 +916,7 @@ public ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) {
912916
return null;
913917
}
914918

915-
public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
919+
public Field lookupField(Collection<Field> fields, ResolvedJavaField key) {
916920
for (Field f : fields) {
917921
if (fieldsEqual(f, key)) {
918922
return f;
@@ -922,9 +926,6 @@ public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
922926
}
923927

924928
private static boolean isHiddenFromReflection(ResolvedJavaField f) {
925-
if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) {
926-
return true;
927-
}
928929
if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(ConstantPool.class)) && f.getName().equals("constantPoolOop")) {
929930
return true;
930931
}
@@ -955,20 +956,28 @@ public void getInstanceFieldsTest() {
955956
for (Class<?> c : classes) {
956957
ResolvedJavaType type = metaAccess.lookupJavaType(c);
957958
for (boolean includeSuperclasses : new boolean[]{true, false}) {
958-
Set<Field> expected = getInstanceFields(c, includeSuperclasses);
959-
ResolvedJavaField[] actual = type.getInstanceFields(includeSuperclasses);
960-
for (Field f : expected) {
961-
assertNotNull(lookupField(actual, f));
959+
List<Field> reflectFields = getInstanceFields(c, includeSuperclasses);
960+
ResolvedJavaField[] fields = type.getInstanceFields(includeSuperclasses);
961+
int reflectFieldIndex = 0;
962+
for (int i = 0; i < fields.length; i++) {
963+
ResolvedJavaField field = fields[i];
964+
if (field.isInternal() || isHiddenFromReflection(field)) {
965+
continue;
966+
}
967+
Field reflectField = reflectFields.get(reflectFieldIndex++);
968+
ResolvedJavaField field2 = lookupField(fields, reflectField);
969+
970+
assertEquals("ResolvedJavaType.getInstanceFields order differs from Class.getDeclaredFields", field, field2);
962971
}
963-
for (ResolvedJavaField rf : actual) {
972+
for (ResolvedJavaField rf : fields) {
964973
if (!isHiddenFromReflection(rf)) {
965-
assertEquals(rf.toString(), lookupField(expected, rf) != null, !rf.isInternal());
974+
assertEquals(rf.toString(), lookupField(reflectFields, rf) != null, !rf.isInternal());
966975
}
967976
}
968977

969978
// Test stability of getInstanceFields
970-
ResolvedJavaField[] actual2 = type.getInstanceFields(includeSuperclasses);
971-
assertArrayEquals(actual, actual2);
979+
ResolvedJavaField[] fields2 = type.getInstanceFields(includeSuperclasses);
980+
assertArrayEquals(fields, fields2);
972981
}
973982
}
974983
}

0 commit comments

Comments
 (0)