mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8213907: [JVMCI] avoid Class.getDeclared* methods when converting JVMCI objects to reflection objects
Reviewed-by: kvn, never
This commit is contained in:
parent
1a6b429e9a
commit
4512750fbe
12 changed files with 175 additions and 114 deletions
|
@ -1498,6 +1498,38 @@ C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_hand
|
|||
}
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
|
||||
methodHandle m = CompilerToVM::asMethod(jvmci_method);
|
||||
oop executable;
|
||||
if (m->is_initializer()) {
|
||||
if (m->is_static_initializer()) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Cannot create java.lang.reflect.Method for class initializer");
|
||||
}
|
||||
executable = Reflection::new_constructor(m, CHECK_NULL);
|
||||
} else {
|
||||
executable = Reflection::new_method(m, false, CHECK_NULL);
|
||||
}
|
||||
return JNIHandles::make_local(thread, executable);
|
||||
}
|
||||
|
||||
C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
|
||||
Klass* klass = CompilerToVM::asKlass(jvmci_type);
|
||||
if (!klass->is_instance_klass()) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
err_msg("Expected non-primitive type, got %s", klass->external_name()));
|
||||
}
|
||||
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||
Array<u2>* fields = iklass->fields();
|
||||
if (index < 0 || index > fields->length()) {
|
||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
|
||||
}
|
||||
fieldDescriptor fd(iklass, index);
|
||||
oop reflected = Reflection::new_field(&fd, CHECK_NULL);
|
||||
return JNIHandles::make_local(env, reflected);
|
||||
}
|
||||
|
||||
#define CC (char*) /*cast a literal from (const char*)*/
|
||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
|
||||
|
||||
|
@ -1519,6 +1551,8 @@ C2V_END
|
|||
#define HS_METADATA "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
|
||||
#define HS_STACK_FRAME_REF "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
|
||||
#define HS_SPECULATION_LOG "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
|
||||
#define REFLECTION_EXECUTABLE "Ljava/lang/reflect/Executable;"
|
||||
#define REFLECTION_FIELD "Ljava/lang/reflect/Field;"
|
||||
#define METASPACE_METHOD_DATA "J"
|
||||
|
||||
JNINativeMethod CompilerToVM::methods[] = {
|
||||
|
@ -1586,6 +1620,8 @@ JNINativeMethod CompilerToVM::methods[] = {
|
|||
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
|
||||
{CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)},
|
||||
{CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)},
|
||||
{CC "asReflectionExecutable", CC "(" HS_RESOLVED_METHOD ")" REFLECTION_EXECUTABLE, FN_PTR(asReflectionExecutable)},
|
||||
{CC "asReflectionField", CC "(" HS_RESOLVED_KLASS "I)" REFLECTION_FIELD, FN_PTR(asReflectionField)},
|
||||
};
|
||||
|
||||
int CompilerToVM::methods_count() {
|
||||
|
|
|
@ -91,6 +91,7 @@ class CompilerToVM {
|
|||
static HeapWord** _heap_end_addr;
|
||||
static HeapWord* volatile* _heap_top_addr;
|
||||
static int _max_oop_map_stack_offset;
|
||||
static int _fields_annotations_base_offset;
|
||||
|
||||
static jbyte* cardtable_start_address;
|
||||
static int cardtable_shift;
|
||||
|
@ -101,7 +102,6 @@ class CompilerToVM {
|
|||
static int sizeof_ExceptionTableElement;
|
||||
static int sizeof_LocalVariableTableElement;
|
||||
static int sizeof_ConstantPool;
|
||||
static int sizeof_SymbolPointer;
|
||||
static int sizeof_narrowKlass;
|
||||
static int sizeof_arrayOopDesc;
|
||||
static int sizeof_BasicLock;
|
||||
|
|
|
@ -61,6 +61,7 @@ bool CompilerToVM::Data::_supports_inline_contig_alloc;
|
|||
HeapWord** CompilerToVM::Data::_heap_end_addr;
|
||||
HeapWord* volatile* CompilerToVM::Data::_heap_top_addr;
|
||||
int CompilerToVM::Data::_max_oop_map_stack_offset;
|
||||
int CompilerToVM::Data::_fields_annotations_base_offset;
|
||||
|
||||
jbyte* CompilerToVM::Data::cardtable_start_address;
|
||||
int CompilerToVM::Data::cardtable_shift;
|
||||
|
@ -71,7 +72,6 @@ int CompilerToVM::Data::sizeof_vtableEntry = sizeof(vtableEntry);
|
|||
int CompilerToVM::Data::sizeof_ExceptionTableElement = sizeof(ExceptionTableElement);
|
||||
int CompilerToVM::Data::sizeof_LocalVariableTableElement = sizeof(LocalVariableTableElement);
|
||||
int CompilerToVM::Data::sizeof_ConstantPool = sizeof(ConstantPool);
|
||||
int CompilerToVM::Data::sizeof_SymbolPointer = sizeof(Symbol*);
|
||||
int CompilerToVM::Data::sizeof_narrowKlass = sizeof(narrowKlass);
|
||||
int CompilerToVM::Data::sizeof_arrayOopDesc = sizeof(arrayOopDesc);
|
||||
int CompilerToVM::Data::sizeof_BasicLock = sizeof(BasicLock);
|
||||
|
@ -122,6 +122,8 @@ void CompilerToVM::Data::initialize(TRAPS) {
|
|||
symbol_init = (address) vmSymbols::object_initializer_name();
|
||||
symbol_clinit = (address) vmSymbols::class_initializer_name();
|
||||
|
||||
_fields_annotations_base_offset = Array<AnnotationArray*>::base_offset_in_bytes();
|
||||
|
||||
BarrierSet* bs = BarrierSet::barrier_set();
|
||||
if (bs->is_a(BarrierSet::CardTableBarrierSet)) {
|
||||
jbyte* base = ci_card_table_address();
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
static_field(CompilerToVM::Data, _heap_top_addr, HeapWord* volatile*) \
|
||||
\
|
||||
static_field(CompilerToVM::Data, _max_oop_map_stack_offset, int) \
|
||||
static_field(CompilerToVM::Data, _fields_annotations_base_offset, int) \
|
||||
\
|
||||
static_field(CompilerToVM::Data, cardtable_start_address, jbyte*) \
|
||||
static_field(CompilerToVM::Data, cardtable_shift, int) \
|
||||
|
@ -86,7 +87,6 @@
|
|||
static_field(CompilerToVM::Data, sizeof_ExceptionTableElement, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_LocalVariableTableElement, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_ConstantPool, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_SymbolPointer, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_narrowKlass, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_arrayOopDesc, int) \
|
||||
static_field(CompilerToVM::Data, sizeof_BasicLock, int) \
|
||||
|
@ -104,6 +104,8 @@
|
|||
\
|
||||
static_field(Abstract_VM_Version, _features, uint64_t) \
|
||||
\
|
||||
nonstatic_field(Annotations, _fields_annotations, Array<AnnotationArray*>*) \
|
||||
\
|
||||
nonstatic_field(Array<int>, _length, int) \
|
||||
unchecked_nonstatic_field(Array<u1>, _data, sizeof(u1)) \
|
||||
unchecked_nonstatic_field(Array<u2>, _data, sizeof(u2)) \
|
||||
|
@ -164,6 +166,7 @@
|
|||
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
|
||||
nonstatic_field(InstanceKlass, _init_state, u1) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u2) \
|
||||
nonstatic_field(InstanceKlass, _annotations, Annotations*) \
|
||||
\
|
||||
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_sp, intptr_t*) \
|
||||
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_pc, address) \
|
||||
|
@ -462,6 +465,8 @@
|
|||
declare_constant(ConstMethod::_has_linenumber_table) \
|
||||
declare_constant(ConstMethod::_has_localvariable_table) \
|
||||
declare_constant(ConstMethod::_has_exception_table) \
|
||||
declare_constant(ConstMethod::_has_method_annotations) \
|
||||
declare_constant(ConstMethod::_has_parameter_annotations) \
|
||||
\
|
||||
declare_constant(CounterData::count_off) \
|
||||
\
|
||||
|
|
|
@ -42,6 +42,8 @@ typedef Array<u1> AnnotationArray;
|
|||
// a type_annotation instance.
|
||||
|
||||
class Annotations: public MetaspaceObj {
|
||||
friend class JVMCIVMStructs;
|
||||
|
||||
// If you add a new field that points to any metaspace object, you
|
||||
// must add this field to Annotations::metaspace_pointers_do().
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import static jdk.vm.ci.common.InitTimer.timer;
|
|||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import jdk.vm.ci.code.BytecodeFrame;
|
||||
import jdk.vm.ci.code.InstalledCode;
|
||||
|
@ -657,4 +658,17 @@ final class CompilerToVM {
|
|||
* Gets the host class for {@code type}.
|
||||
*/
|
||||
native HotSpotResolvedObjectTypeImpl getHostClass(HotSpotResolvedObjectTypeImpl type);
|
||||
|
||||
/**
|
||||
* Gets a {@link Executable} corresponding to {@code method}.
|
||||
*/
|
||||
native Executable asReflectionExecutable(HotSpotResolvedJavaMethodImpl method);
|
||||
|
||||
/**
|
||||
* Gets a {@link Field} denoted by {@code holder} and {@code index}.
|
||||
*
|
||||
* @param holder the class in which the requested field is declared
|
||||
* @param fieldIndex the {@code fieldDescriptor::index()} denoting the field
|
||||
*/
|
||||
native Field asReflectionField(HotSpotResolvedObjectTypeImpl holder, int fieldIndex);
|
||||
}
|
||||
|
|
|
@ -22,11 +22,15 @@
|
|||
*/
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.internal.misc.Unsafe.ADDRESS_SIZE;
|
||||
import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
|
||||
import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers;
|
||||
import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
|
||||
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
|
||||
import jdk.vm.ci.meta.JavaConstant;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
|
@ -156,41 +160,65 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||
return (config().jvmAccFieldStable & modifiers) != 0;
|
||||
}
|
||||
|
||||
private boolean hasAnnotations() {
|
||||
if (!isInternal()) {
|
||||
HotSpotVMConfig config = config();
|
||||
final long metaspaceAnnotations = UNSAFE.getAddress(holder.getMetaspaceKlass() + config.instanceKlassAnnotationsOffset);
|
||||
if (metaspaceAnnotations != 0) {
|
||||
long fieldsAnnotations = UNSAFE.getAddress(metaspaceAnnotations + config.annotationsFieldAnnotationsOffset);
|
||||
if (fieldsAnnotations != 0) {
|
||||
long fieldAnnotations = UNSAFE.getAddress(fieldsAnnotations + config.fieldsAnnotationsBaseOffset + (ADDRESS_SIZE * index));
|
||||
return fieldAnnotations != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotations() {
|
||||
Field javaField = toJava();
|
||||
if (javaField != null) {
|
||||
return javaField.getAnnotations();
|
||||
}
|
||||
if (!hasAnnotations()) {
|
||||
return new Annotation[0];
|
||||
}
|
||||
return toJava().getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
Field javaField = toJava();
|
||||
if (javaField != null) {
|
||||
return javaField.getDeclaredAnnotations();
|
||||
}
|
||||
if (!hasAnnotations()) {
|
||||
return new Annotation[0];
|
||||
}
|
||||
return toJava().getDeclaredAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
Field javaField = toJava();
|
||||
if (javaField != null) {
|
||||
return javaField.getAnnotation(annotationClass);
|
||||
}
|
||||
if (!hasAnnotations()) {
|
||||
return null;
|
||||
}
|
||||
return toJava().getAnnotation(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Field} object corresponding to this object. This method always returns the same
|
||||
* {@link Field} object for a given {@link HotSpotResolvedJavaFieldImpl}. This ensures
|
||||
* {@link #getDeclaredAnnotations()}, {@link #getAnnotations()} and
|
||||
* {@link #getAnnotation(Class)} are stable with respect to the identity of the
|
||||
* {@link Annotation} objects they return.
|
||||
*/
|
||||
private Field toJava() {
|
||||
if (isInternal()) {
|
||||
return null;
|
||||
synchronized (holder) {
|
||||
HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = holder.reflectionFieldCache;
|
||||
if (cache == null) {
|
||||
cache = new HashMap<>();
|
||||
holder.reflectionFieldCache = cache;
|
||||
}
|
||||
try {
|
||||
return holder.mirror().getDeclaredField(getName());
|
||||
} catch (NoSuchFieldException e) {
|
||||
return null;
|
||||
Field reflect = cache.get(this);
|
||||
if (reflect == null) {
|
||||
reflect = compilerToVM().asReflectionField(holder, index);
|
||||
cache.put(this, reflect);
|
||||
}
|
||||
return reflect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,8 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
|||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -54,7 +52,6 @@ import jdk.vm.ci.meta.LocalVariableTable;
|
|||
import jdk.vm.ci.meta.ProfilingInfo;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.meta.Signature;
|
||||
import jdk.vm.ci.meta.SpeculationLog;
|
||||
import jdk.vm.ci.meta.TriState;
|
||||
|
||||
|
@ -75,11 +72,9 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
|||
private byte[] code;
|
||||
|
||||
/**
|
||||
* Cache for {@link #toJava()}. Set to {@link #signature} when resolving reflection object fails
|
||||
* due to reflection filtering (see {@code Reflection.fieldFilterMap} and
|
||||
* {@code Reflection.methodFilterMap}).
|
||||
* Cache for {@link #toJava()}.
|
||||
*/
|
||||
private Object toJavaCache;
|
||||
private volatile Executable toJavaCache;
|
||||
|
||||
/**
|
||||
* Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
|
||||
|
@ -492,12 +487,10 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
|||
|
||||
@Override
|
||||
public Parameter[] getParameters() {
|
||||
Executable javaMethod = toJava();
|
||||
if (javaMethod == null) {
|
||||
return null;
|
||||
if (signature.getParameterCount(false) == 0) {
|
||||
return new ResolvedJavaMethod.Parameter[0];
|
||||
}
|
||||
|
||||
java.lang.reflect.Parameter[] javaParameters = javaMethod.getParameters();
|
||||
java.lang.reflect.Parameter[] javaParameters = toJava().getParameters();
|
||||
Parameter[] res = new Parameter[javaParameters.length];
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
java.lang.reflect.Parameter src = javaParameters[i];
|
||||
|
@ -509,32 +502,34 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
|||
|
||||
@Override
|
||||
public Annotation[][] getParameterAnnotations() {
|
||||
Executable javaMethod = toJava();
|
||||
return javaMethod == null ? new Annotation[signature.getParameterCount(false)][0] : javaMethod.getParameterAnnotations();
|
||||
if ((getConstMethodFlags() & config().constMethodHasParameterAnnotations) == 0) {
|
||||
return new Annotation[signature.getParameterCount(false)][0];
|
||||
}
|
||||
return toJava().getParameterAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getAnnotations() {
|
||||
Executable javaMethod = toJava();
|
||||
if (javaMethod != null) {
|
||||
return javaMethod.getAnnotations();
|
||||
}
|
||||
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
|
||||
return new Annotation[0];
|
||||
}
|
||||
return toJava().getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
Executable javaMethod = toJava();
|
||||
if (javaMethod != null) {
|
||||
return javaMethod.getDeclaredAnnotations();
|
||||
}
|
||||
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
|
||||
return new Annotation[0];
|
||||
}
|
||||
return toJava().getDeclaredAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
Executable javaMethod = toJava();
|
||||
return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
|
||||
if ((getConstMethodFlags() & config().constMethodHasMethodAnnotations) == 0) {
|
||||
return null;
|
||||
}
|
||||
return toJava().getAnnotation(annotationClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -561,60 +556,22 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
|||
|
||||
@Override
|
||||
public Type[] getGenericParameterTypes() {
|
||||
Executable javaMethod = toJava();
|
||||
return javaMethod == null ? null : javaMethod.getGenericParameterTypes();
|
||||
if (isClassInitializer()) {
|
||||
return new Type[0];
|
||||
}
|
||||
|
||||
public Class<?>[] signatureToTypes() {
|
||||
Signature sig = getSignature();
|
||||
int count = sig.getParameterCount(false);
|
||||
Class<?>[] result = new Class<?>[count];
|
||||
for (int i = 0; i < result.length; ++i) {
|
||||
JavaType parameterType = sig.getParameterType(i, holder);
|
||||
HotSpotResolvedJavaType resolvedParameterType = (HotSpotResolvedJavaType) parameterType.resolve(holder);
|
||||
result[i] = resolvedParameterType.mirror();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Method searchMethods(Method[] methods, String name, Class<?> returnType, Class<?>[] parameterTypes) {
|
||||
for (Method m : methods) {
|
||||
if (m.getName().equals(name) && returnType.equals(m.getReturnType()) && Arrays.equals(m.getParameterTypes(), parameterTypes)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return toJava().getGenericParameterTypes();
|
||||
}
|
||||
|
||||
private Executable toJava() {
|
||||
if (toJavaCache != null) {
|
||||
if (toJavaCache == signature) {
|
||||
return null;
|
||||
}
|
||||
return (Executable) toJavaCache;
|
||||
}
|
||||
Class<?>[] parameterTypes = signatureToTypes();
|
||||
Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
|
||||
|
||||
Executable result;
|
||||
if (isConstructor()) {
|
||||
try {
|
||||
result = holder.mirror().getDeclaredConstructor(parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
toJavaCache = signature;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// Do not use Method.getDeclaredMethod() as it can return a bridge method
|
||||
// when this.isBridge() is false and vice versa.
|
||||
result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
|
||||
if (result == null) {
|
||||
toJavaCache = signature;
|
||||
return null;
|
||||
if (toJavaCache == null) {
|
||||
assert !isClassInitializer() : this;
|
||||
synchronized (this) {
|
||||
if (toJavaCache == null) {
|
||||
toJavaCache = compilerToVM().asReflectionExecutable(this);
|
||||
}
|
||||
}
|
||||
toJavaCache = result;
|
||||
return result;
|
||||
}
|
||||
return toJavaCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,6 +33,7 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
|||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteOrder;
|
||||
|
@ -74,6 +75,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||
final HotSpotJVMCIMetaAccessContext context;
|
||||
private HotSpotResolvedObjectType arrayOfType;
|
||||
|
||||
/**
|
||||
* Managed exclusively by {@link HotSpotResolvedJavaFieldImpl#toJava}.
|
||||
*/
|
||||
HashMap<HotSpotResolvedJavaFieldImpl, Field> reflectionFieldCache;
|
||||
|
||||
/**
|
||||
* Gets the JVMCI mirror for a {@link Class} object.
|
||||
*
|
||||
|
|
|
@ -94,6 +94,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
|
||||
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
|
||||
final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
|
||||
final int instanceKlassAnnotationsOffset = getFieldOffset("InstanceKlass::_annotations", Integer.class, "Annotations*");
|
||||
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u2");
|
||||
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
|
||||
final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
|
||||
|
@ -102,6 +103,9 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
|
||||
final int instanceKlassMiscIsUnsafeAnonymous = getConstant("InstanceKlass::_misc_is_unsafe_anonymous", Integer.class);
|
||||
|
||||
final int annotationsFieldAnnotationsOffset = getFieldOffset("Annotations::_fields_annotations", Integer.class, "Array<AnnotationArray*>*");
|
||||
final int fieldsAnnotationsBaseOffset = getFieldValue("CompilerToVM::Data::_fields_annotations_base_offset", Integer.class, "int");
|
||||
|
||||
final int arrayU1LengthOffset = getFieldOffset("Array<int>::_length", Integer.class, "int");
|
||||
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
|
||||
final int arrayU2DataOffset = getFieldOffset("Array<u2>::_data", Integer.class);
|
||||
|
@ -195,6 +199,8 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
|
||||
final int constMethodHasLineNumberTable = getConstant("ConstMethod::_has_linenumber_table", Integer.class);
|
||||
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
|
||||
final int constMethodHasMethodAnnotations = getConstant("ConstMethod::_has_method_annotations", Integer.class);
|
||||
final int constMethodHasParameterAnnotations = getConstant("ConstMethod::_has_parameter_annotations", Integer.class);
|
||||
final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
|
||||
|
||||
final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
|
||||
|
@ -244,8 +250,6 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
|
||||
final int heapWordSize = getConstant("HeapWordSize", Integer.class);
|
||||
|
||||
final int symbolPointerSize = getFieldValue("CompilerToVM::Data::sizeof_SymbolPointer", Integer.class, "int");
|
||||
|
||||
final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
|
||||
final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
|
||||
final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
|
||||
|
@ -263,8 +267,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
String symbolAt(int index) {
|
||||
HotSpotJVMCIRuntime runtime = runtime();
|
||||
assert vmSymbolsFirstSID <= index && index < vmSymbolsSIDLimit : "index " + index + " is out of bounds";
|
||||
assert symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
|
||||
int offset = index * symbolPointerSize;
|
||||
int offset = index * Unsafe.ADDRESS_SIZE;
|
||||
return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(vmSymbolsSymbols + offset));
|
||||
}
|
||||
|
||||
|
|
|
@ -142,16 +142,15 @@ public class TestResolvedJavaField extends FieldUniverse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String NON_EXISTENT_CLASS_NAME = "XXXXXXXXXXX";
|
||||
|
||||
static class TestClassLoader extends ClassLoader {
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(final String name) {
|
||||
protected Class<?> findClass(final String name) throws ClassNotFoundException {
|
||||
if (!name.equals(TypeWithUnresolvedFieldType.class.getName())) {
|
||||
try {
|
||||
return super.findClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError("unexpected: " + e);
|
||||
}
|
||||
}
|
||||
// copy classfile to byte array
|
||||
byte[] classData = null;
|
||||
|
@ -176,7 +175,7 @@ public class TestResolvedJavaField extends FieldUniverse {
|
|||
int index = -1;
|
||||
|
||||
while ((index = indexOf(classData, index + 1, "PrintStream")) != -1) {
|
||||
replace(classData, index, "XXXXXXXXXXX");
|
||||
replace(classData, index, NON_EXISTENT_CLASS_NAME);
|
||||
}
|
||||
|
||||
Class<?> c = defineClass(null, classData, 0, classData.length);
|
||||
|
@ -211,13 +210,14 @@ public class TestResolvedJavaField extends FieldUniverse {
|
|||
* type of the field is not resolvable.
|
||||
*/
|
||||
@Test
|
||||
public void testGetType() {
|
||||
public void testGetType() throws ClassNotFoundException {
|
||||
Class<?> c = new TestClassLoader().findClass(TypeWithUnresolvedFieldType.class.getName());
|
||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||
for (ResolvedJavaField field : type.getInstanceFields(false)) {
|
||||
assertTrue(field.getName().equals("fieldWithUnresolvableType"));
|
||||
field.getType();
|
||||
field.toString();
|
||||
field.getAnnotations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -855,17 +855,25 @@ public class TestResolvedJavaType extends TypeUniverse {
|
|||
|
||||
}
|
||||
|
||||
private static ResolvedJavaMethod getClassInitializer(Class<?> c) {
|
||||
ResolvedJavaMethod clinit = metaAccess.lookupJavaType(c).getClassInitializer();
|
||||
if (clinit != null) {
|
||||
assertEquals(0, clinit.getAnnotations().length);
|
||||
assertEquals(0, clinit.getDeclaredAnnotations().length);
|
||||
}
|
||||
return clinit;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getClassInitializerTest() {
|
||||
assertNotNull(metaAccess.lookupJavaType(A.class).getClassInitializer());
|
||||
assertNotNull(metaAccess.lookupJavaType(D.class).getClassInitializer());
|
||||
assertNull(metaAccess.lookupJavaType(B.class).getClassInitializer());
|
||||
assertNull(metaAccess.lookupJavaType(C.class).getClassInitializer());
|
||||
assertNull(metaAccess.lookupJavaType(int.class).getClassInitializer());
|
||||
assertNull(metaAccess.lookupJavaType(void.class).getClassInitializer());
|
||||
assertNotNull(getClassInitializer(A.class));
|
||||
assertNotNull(getClassInitializer(D.class));
|
||||
assertNull(getClassInitializer(B.class));
|
||||
assertNull(getClassInitializer(C.class));
|
||||
assertNull(getClassInitializer(int.class));
|
||||
assertNull(getClassInitializer(void.class));
|
||||
for (Class<?> c : classes) {
|
||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||
type.getClassInitializer();
|
||||
getClassInitializer(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue