mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-01 03:30:34 +00:00
8350892: [JVMCI] Align ResolvedJavaType.getInstanceFields with Class.getDeclaredFields
Reviewed-by: yzheng, never, thartmann
This commit is contained in:
parent
04eac0c3e2
commit
0cb110ebb7
@ -400,9 +400,6 @@ ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static)
|
||||
int field_off = field->offset_in_bytes();
|
||||
if (field_off == field_offset)
|
||||
return field;
|
||||
if (field_off > field_offset)
|
||||
break;
|
||||
// could do binary search or check bins, but probably not worth it
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -431,11 +428,6 @@ ciField* ciInstanceKlass::get_field_by_name(ciSymbol* name, ciSymbol* signature,
|
||||
}
|
||||
|
||||
|
||||
static int sort_field_by_offset(ciField** a, ciField** b) {
|
||||
return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
|
||||
// (no worries about 32-bit overflow...)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::compute_nonstatic_fields
|
||||
int ciInstanceKlass::compute_nonstatic_fields() {
|
||||
@ -476,9 +468,6 @@ int ciInstanceKlass::compute_nonstatic_fields() {
|
||||
|
||||
int flen = fields->length();
|
||||
|
||||
// Now sort them by offset, ascending.
|
||||
// (In principle, they could mix with superclass fields.)
|
||||
fields->sort(sort_field_by_offset);
|
||||
_nonstatic_fields = fields;
|
||||
return flen;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ private:
|
||||
ciInstance* _java_mirror;
|
||||
|
||||
ciConstantPoolCache* _field_cache; // cached map index->field
|
||||
GrowableArray<ciField*>* _nonstatic_fields;
|
||||
GrowableArray<ciField*>* _nonstatic_fields; // ordered by JavaFieldStream
|
||||
int _has_injected_fields; // any non static injected fields? lazily initialized.
|
||||
|
||||
// The possible values of the _implementor fall into following three cases:
|
||||
|
||||
@ -377,8 +377,9 @@ static bool rematerialize_objects(JavaThread* thread, int exec_mode, nmethod* co
|
||||
realloc_failures = Deoptimization::realloc_objects(thread, &deoptee, &map, objects, THREAD);
|
||||
JRT_END
|
||||
}
|
||||
bool skip_internal = (compiled_method != nullptr) && !compiled_method->is_compiled_by_jvmci();
|
||||
Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, skip_internal);
|
||||
guarantee(compiled_method != nullptr, "deopt must be associated with an nmethod");
|
||||
bool is_jvmci = compiled_method->is_compiled_by_jvmci();
|
||||
Deoptimization::reassign_fields(&deoptee, &map, objects, realloc_failures, is_jvmci);
|
||||
if (TraceDeoptimization) {
|
||||
print_objects(deoptee_thread, objects, realloc_failures);
|
||||
}
|
||||
@ -1458,27 +1459,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static int compare(ReassignedField* left, ReassignedField* right) {
|
||||
return left->_offset - right->_offset;
|
||||
// Gets the fields of `klass` that are eliminated by escape analysis and need to be reassigned
|
||||
static GrowableArray<ReassignedField>* get_reassigned_fields(InstanceKlass* klass, GrowableArray<ReassignedField>* fields, bool is_jvmci) {
|
||||
InstanceKlass* super = klass->superklass();
|
||||
if (super != nullptr) {
|
||||
get_reassigned_fields(super, fields, is_jvmci);
|
||||
}
|
||||
for (AllFieldStream fs(klass); !fs.done(); fs.next()) {
|
||||
if (!fs.access_flags().is_static() && (is_jvmci || !fs.field_flags().is_injected())) {
|
||||
ReassignedField field;
|
||||
field._offset = fs.offset();
|
||||
field._type = Signature::basic_type(fs.signature());
|
||||
fields->append(field);
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
// Restore fields of an eliminated instance object using the same field order
|
||||
// returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true)
|
||||
static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal) {
|
||||
GrowableArray<ReassignedField>* fields = new GrowableArray<ReassignedField>();
|
||||
InstanceKlass* ik = klass;
|
||||
while (ik != nullptr) {
|
||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||
if (!fs.access_flags().is_static() && (!skip_internal || !fs.field_flags().is_injected())) {
|
||||
ReassignedField field;
|
||||
field._offset = fs.offset();
|
||||
field._type = Signature::basic_type(fs.signature());
|
||||
fields->append(field);
|
||||
}
|
||||
}
|
||||
ik = ik->superklass();
|
||||
}
|
||||
fields->sort(compare);
|
||||
// Restore fields of an eliminated instance object employing the same field order used by the compiler.
|
||||
static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool is_jvmci) {
|
||||
GrowableArray<ReassignedField>* fields = get_reassigned_fields(klass, new GrowableArray<ReassignedField>(), is_jvmci);
|
||||
for (int i = 0; i < fields->length(); i++) {
|
||||
ScopeValue* scope_field = sv->field_at(svIndex);
|
||||
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
|
||||
}
|
||||
|
||||
// restore fields of all eliminated objects and arrays
|
||||
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool skip_internal) {
|
||||
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures, bool is_jvmci) {
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
assert(objects->at(i)->is_object(), "invalid debug information");
|
||||
ObjectValue* sv = (ObjectValue*) objects->at(i);
|
||||
@ -1604,7 +1604,7 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
|
||||
}
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
|
||||
reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), is_jvmci);
|
||||
} else if (k->is_typeArray_klass()) {
|
||||
TypeArrayKlass* ak = TypeArrayKlass::cast(k);
|
||||
reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());
|
||||
|
||||
@ -67,7 +67,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
|
||||
private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
|
||||
private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
|
||||
private static final SortByOffset fieldSortingMethod = new SortByOffset();
|
||||
|
||||
/**
|
||||
* The {@code Klass*} of this type.
|
||||
@ -782,12 +781,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
}
|
||||
}
|
||||
|
||||
static class SortByOffset implements Comparator<ResolvedJavaField> {
|
||||
public int compare(ResolvedJavaField a, ResolvedJavaField b) {
|
||||
return a.getOffset() - b.getOffset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
|
||||
if (instanceFields == null) {
|
||||
@ -817,7 +810,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
result[i++] = f;
|
||||
}
|
||||
}
|
||||
Arrays.sort(result, fieldSortingMethod);
|
||||
return result;
|
||||
} else {
|
||||
// The super classes of this class do not have any instance fields.
|
||||
@ -876,7 +868,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
result[resultIndex++] = resolvedJavaField;
|
||||
}
|
||||
}
|
||||
Arrays.sort(result, fieldSortingMethod);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -284,24 +284,21 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
|
||||
AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
|
||||
|
||||
/**
|
||||
* Returns the instance fields of this class, including
|
||||
* Returns the non-static fields of this class, including
|
||||
* {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
|
||||
* for array and primitive types. The order of fields returned by this method is stable. That
|
||||
* is, for a single JVM execution the same order is returned each time this method is called. It
|
||||
* is also the "natural" order, which means that the JVM would expect the fields in this order
|
||||
* if no specific order is given.
|
||||
* for array and primitive types. The order of fields declared by a single class returned by
|
||||
* this method is the same as {@link Class#getDeclaredFields}.
|
||||
*
|
||||
* @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
|
||||
* type are included in the result
|
||||
* @return an array of instance fields
|
||||
* @param includeSuperclasses if true, then non-static fields for the complete hierarchy of this
|
||||
* type are included in the result with superclass fields coming before subclass fields
|
||||
* @return an array of non-static fields
|
||||
*/
|
||||
ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses);
|
||||
|
||||
/**
|
||||
* Returns the static fields of this class, including {@linkplain ResolvedJavaField#isInternal()
|
||||
* internal} fields. A zero-length array is returned for array and primitive types. The order of
|
||||
* fields returned by this method is stable. That is, for a single JVM execution the same order
|
||||
* is returned each time this method is called.
|
||||
* fields returned by this method is the same as {@link Class#getDeclaredFields}.
|
||||
*/
|
||||
ResolvedJavaField[] getStaticFields();
|
||||
|
||||
|
||||
@ -71,7 +71,9 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
@ -144,7 +146,7 @@ public class TestResolvedJavaType extends TypeUniverse {
|
||||
public void findInstanceFieldWithOffsetTest() {
|
||||
for (Class<?> c : classes) {
|
||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||
Set<Field> reflectionFields = getInstanceFields(c, true);
|
||||
Set<Field> reflectionFields = Set.copyOf(getInstanceFields(c, true));
|
||||
for (Field f : reflectionFields) {
|
||||
ResolvedJavaField rf = lookupField(type.getInstanceFields(true), f);
|
||||
assertNotNull(rf);
|
||||
@ -872,18 +874,20 @@ public class TestResolvedJavaType extends TypeUniverse {
|
||||
assertEquals(thisMethod, ucm);
|
||||
}
|
||||
|
||||
public static Set<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
|
||||
public static List<Field> getInstanceFields(Class<?> c, boolean includeSuperclasses) {
|
||||
if (c.isArray() || c.isPrimitive() || c.isInterface()) {
|
||||
return Collections.emptySet();
|
||||
return List.of();
|
||||
}
|
||||
Set<Field> result = new HashSet<>();
|
||||
List<Field> result = new ArrayList<>();
|
||||
for (Field f : c.getDeclaredFields()) {
|
||||
if (!Modifier.isStatic(f.getModifiers())) {
|
||||
result.add(f);
|
||||
}
|
||||
}
|
||||
if (includeSuperclasses && c != Object.class) {
|
||||
result.addAll(getInstanceFields(c.getSuperclass(), true));
|
||||
List<Field> allFields = getInstanceFields(c.getSuperclass(), true);
|
||||
allFields.addAll(result);
|
||||
result = allFields;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -912,7 +916,7 @@ public class TestResolvedJavaType extends TypeUniverse {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Field lookupField(Set<Field> fields, ResolvedJavaField key) {
|
||||
public Field lookupField(Collection<Field> fields, ResolvedJavaField key) {
|
||||
for (Field f : fields) {
|
||||
if (fieldsEqual(f, key)) {
|
||||
return f;
|
||||
@ -922,9 +926,6 @@ public class TestResolvedJavaType extends TypeUniverse {
|
||||
}
|
||||
|
||||
private static boolean isHiddenFromReflection(ResolvedJavaField f) {
|
||||
if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) {
|
||||
return true;
|
||||
}
|
||||
if (f.getDeclaringClass().equals(metaAccess.lookupJavaType(ConstantPool.class)) && f.getName().equals("constantPoolOop")) {
|
||||
return true;
|
||||
}
|
||||
@ -955,20 +956,28 @@ public class TestResolvedJavaType extends TypeUniverse {
|
||||
for (Class<?> c : classes) {
|
||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||
for (boolean includeSuperclasses : new boolean[]{true, false}) {
|
||||
Set<Field> expected = getInstanceFields(c, includeSuperclasses);
|
||||
ResolvedJavaField[] actual = type.getInstanceFields(includeSuperclasses);
|
||||
for (Field f : expected) {
|
||||
assertNotNull(lookupField(actual, f));
|
||||
List<Field> reflectFields = getInstanceFields(c, includeSuperclasses);
|
||||
ResolvedJavaField[] fields = type.getInstanceFields(includeSuperclasses);
|
||||
int reflectFieldIndex = 0;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
ResolvedJavaField field = fields[i];
|
||||
if (field.isInternal() || isHiddenFromReflection(field)) {
|
||||
continue;
|
||||
}
|
||||
Field reflectField = reflectFields.get(reflectFieldIndex++);
|
||||
ResolvedJavaField field2 = lookupField(fields, reflectField);
|
||||
|
||||
assertEquals("ResolvedJavaType.getInstanceFields order differs from Class.getDeclaredFields", field, field2);
|
||||
}
|
||||
for (ResolvedJavaField rf : actual) {
|
||||
for (ResolvedJavaField rf : fields) {
|
||||
if (!isHiddenFromReflection(rf)) {
|
||||
assertEquals(rf.toString(), lookupField(expected, rf) != null, !rf.isInternal());
|
||||
assertEquals(rf.toString(), lookupField(reflectFields, rf) != null, !rf.isInternal());
|
||||
}
|
||||
}
|
||||
|
||||
// Test stability of getInstanceFields
|
||||
ResolvedJavaField[] actual2 = type.getInstanceFields(includeSuperclasses);
|
||||
assertArrayEquals(actual, actual2);
|
||||
ResolvedJavaField[] fields2 = type.getInstanceFields(includeSuperclasses);
|
||||
assertArrayEquals(fields, fields2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user