8225810: Update JVMCI

Reviewed-by: never, dnsimon
This commit is contained in:
Vladimir Kozlov 2019-06-21 16:21:13 -07:00
parent c956e7ca8d
commit 3b0ee5a6d8
15 changed files with 380 additions and 43 deletions

View File

@ -568,6 +568,33 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla
return JVMCIENV->get_jobject(result);
C2V_END
C2V_VMENTRY_NULL(jobject, getArrayType, (JNIEnv* env, jobject, jobject jvmci_type))
if (jvmci_type == NULL) {
JVMCI_THROW_0(NullPointerException);
}
JVMCIObject jvmci_type_object = JVMCIENV->wrap(jvmci_type);
JVMCIKlassHandle array_klass(THREAD);
if (JVMCIENV->isa_HotSpotResolvedPrimitiveType(jvmci_type_object)) {
BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(jvmci_type_object), JVMCI_CHECK_0);
if (type == T_VOID) {
return NULL;
}
array_klass = Universe::typeArrayKlassObj(type);
if (array_klass == NULL) {
JVMCI_THROW_MSG_NULL(InternalError, err_msg("No array klass for primitive type %s", type2name(type)));
}
} else {
Klass* klass = JVMCIENV->asKlass(jvmci_type);
if (klass == NULL) {
JVMCI_THROW_0(NullPointerException);
}
array_klass = klass->array_klass(CHECK_NULL);
}
JVMCIObject result = JVMCIENV->get_jvmci_type(array_klass, JVMCI_CHECK_NULL);
return JVMCIENV->get_jobject(result);
C2V_END
C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
requireInHotSpot("lookupClass", JVMCI_CHECK_NULL);
if (mirror == NULL) {
@ -2578,6 +2605,18 @@ C2V_VMENTRY_0(jboolean, addFailedSpeculation, (JNIEnv* env, jobject, jlong faile
return FailedSpeculation::add_failed_speculation(NULL, (FailedSpeculation**)(address) failed_speculations_address, (address) speculation, speculation_len);
}
C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status))
JavaValue result(T_VOID);
JavaCallArguments jargs(1);
jargs.push_int(status);
JavaCalls::call_static(&result,
SystemDictionary::System_klass(),
vmSymbols::exit_method_name(),
vmSymbols::int_void_signature(),
&jargs,
CHECK);
}
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@ -2624,6 +2663,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
{CC "lookupType", CC "(" STRING HS_RESOLVED_KLASS "Z)" HS_RESOLVED_TYPE, FN_PTR(lookupType)},
{CC "getArrayType", CC "(" HS_RESOLVED_TYPE ")" HS_RESOLVED_KLASS, FN_PTR(getArrayType)},
{CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)},
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},
{CC "lookupNameAndTypeRefIndexInPool", CC "(" HS_CONSTANT_POOL "I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)},
@ -2723,6 +2763,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getFailedSpeculationsAddress", CC "(" HS_RESOLVED_METHOD ")J", FN_PTR(getFailedSpeculationsAddress)},
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
{CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)},
};
int CompilerToVM::methods_count() {

View File

@ -1361,6 +1361,9 @@ Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
return Handle(THREAD, obj);
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
if (object_handle == 0L) {
JVMCI_THROW_MSG_(NullPointerException, "Foreign object reference has been cleared", Handle());
}
oop result = resolve_handle(object_handle);
if (result == NULL) {
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());

View File

@ -770,6 +770,12 @@ final class CompilerToVM {
*/
native HotSpotResolvedJavaType getComponentType(HotSpotResolvedObjectTypeImpl type);
/**
* Get the array class for {@code type}. This can't be done symbolically since anonymous types
* can't be looked up by name.
*/
native HotSpotResolvedObjectTypeImpl getArrayType(HotSpotResolvedJavaType type);
/**
* Forces initialization of {@code type}.
*/
@ -978,4 +984,9 @@ final class CompilerToVM {
* @see HotSpotJVMCIRuntime#detachCurrentThread()
*/
native void detachCurrentThread();
/**
* @see HotSpotJVMCIRuntime#exitHotSpot(int)
*/
native void callSystemExit(int status);
}

View File

@ -87,4 +87,9 @@ public class HotSpotCompilationRequest extends CompilationRequest {
public int getId() {
return id;
}
@Override
public String toString() {
return id + ":" + super.toString();
}
}

View File

@ -223,6 +223,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
// so that -XX:+JVMCIPrintProperties shows the option.
InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " +
"to debug issue with a wrapper being used after its scope has closed."),
TraceMethodDataFilter(String.class, null,
"Enables tracing of profiling info when read by JVMCI.",
"Empty value: trace all methods",
@ -687,9 +689,11 @@ assert factories != null : "sanity";
return Collections.unmodifiableMap(backends);
}
@SuppressWarnings("try")
@VMEntryPoint
private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, compileState, id));
HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, compileState, id);
CompilationRequestResult result = getCompiler().compileMethod(request);
assert result != null : "compileMethod must always return something";
HotSpotCompilationRequestResult hsResult;
if (result instanceof HotSpotCompilationRequestResult) {
@ -704,7 +708,6 @@ assert factories != null : "sanity";
hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
}
}
return hsResult;
}
@ -1032,4 +1035,14 @@ assert factories != null : "sanity";
public void excludeFromJVMCICompilation(Module...modules) {
this.excludeFromJVMCICompilation = modules.clone();
}
/**
* Calls {@link System#exit(int)} in HotSpot's runtime.
*/
public void exitHotSpot(int status) {
if (!IS_IN_NATIVE_IMAGE) {
System.exit(status);
}
compilerToVm.callSystemExit(status);
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.hotspot;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import jdk.vm.ci.services.Services;
/**
* A mechanism for limiting the lifetime of a foreign object reference encapsulated in a
* {@link HotSpotObjectConstant}.
*
* A {@link HotSpotObjectConstant} allocated in a {@linkplain #openLocalScope local} scope will have
* its reference to any foreign object cleared when the scope {@linkplain #close() closes}. This
* allows the foreign memory manager to reclaim the foreign object (once there are no other strong
* references to it).
*
* {@link HotSpotObjectConstantScope}s have no impact on {@link HotSpotObjectConstant}s that do not
* encapsulate a foreign object reference.
*
* The object returned by {@link #enterGlobalScope()} or {@link #openLocalScope(Object)} should
* always be used in a try-with-resources statement. Failure to close a scope will almost certainly
* result in foreign objects being leaked.
*/
public final class HotSpotObjectConstantScope implements AutoCloseable {
static final ThreadLocal<HotSpotObjectConstantScope> CURRENT = new ThreadLocal<>();
private final HotSpotObjectConstantScope parent;
private List<IndirectHotSpotObjectConstantImpl> foreignObjects;
/**
* An object whose {@link Object#toString()} value describes a non-global scope. This is
* {@code null} iff this is a global scope.
*/
final Object localScopeDescription;
/**
* Opens a local scope that upon closing, will release foreign object references encapsulated by
* {@link HotSpotObjectConstant}s created in the scope.
*
* @param description an non-null object whose {@link Object#toString()} value describes the
* scope being opened
* @return {@code null} if the current runtime does not support remote object references
*/
public static HotSpotObjectConstantScope openLocalScope(Object description) {
return Services.IS_IN_NATIVE_IMAGE ? new HotSpotObjectConstantScope(Objects.requireNonNull(description)) : null;
}
/**
* Enters the global scope. This is useful to escape a local scope for execution that will
* create foreign object references that need to outlive the local scope.
*
* Foreign object references encapsulated by {@link HotSpotObjectConstant}s created in the
* global scope are only subject to reclamation once the {@link HotSpotObjectConstant} wrapper
* dies.
*
* @return {@code null} if the current runtime does not support remote object references or if
* this thread is currently in the global scope
*/
public static HotSpotObjectConstantScope enterGlobalScope() {
return Services.IS_IN_NATIVE_IMAGE && CURRENT.get() != null ? new HotSpotObjectConstantScope(null) : null;
}
private HotSpotObjectConstantScope(Object localScopeDescription) {
this.parent = CURRENT.get();
CURRENT.set(this);
this.localScopeDescription = localScopeDescription;
}
/**
* Determines if this scope is global.
*/
boolean isGlobal() {
return localScopeDescription == null;
}
void add(IndirectHotSpotObjectConstantImpl obj) {
assert !isGlobal();
if (foreignObjects == null) {
foreignObjects = new ArrayList<>();
}
foreignObjects.add(obj);
}
@VMEntryPoint
@Override
public void close() {
if (CURRENT.get() != this) {
throw new IllegalStateException("Cannot close non-active scope");
}
if (foreignObjects != null) {
for (IndirectHotSpotObjectConstantImpl obj : foreignObjects) {
obj.clear(localScopeDescription);
}
foreignObjects = null;
}
CURRENT.set(parent);
}
}

View File

@ -22,11 +22,15 @@
*/
package jdk.vm.ci.hotspot;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaType;
public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
HotSpotResolvedObjectTypeImpl arrayOfType;
HotSpotResolvedJavaType(String name) {
super(name);
}
@ -40,4 +44,12 @@ public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements
}
abstract JavaConstant getJavaMirror();
@Override
public HotSpotResolvedObjectType getArrayClass() {
if (arrayOfType == null) {
arrayOfType = runtime().compilerToVm.getArrayType(this);
}
return arrayOfType;
}
}

View File

@ -72,7 +72,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
private volatile HotSpotResolvedJavaField[] instanceFields;
private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
private HotSpotConstantPool constantPool;
private HotSpotResolvedObjectType arrayOfType;
private final JavaConstant mirror;
private HotSpotResolvedObjectTypeImpl superClass;
@ -103,17 +102,24 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
* Creates the JVMCI mirror for a {@link Class} object.
*
* <b>NOTE</b>: Creating an instance of this class does not install the mirror for the
* {@link Class} type. {@link #fromMetaspace} instead.
* {@link Class} type.
* </p>
*
* @param metadataPointer the Klass* to create the mirror for
*/
@SuppressWarnings("try")
HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
super(name);
this.metadataPointer = metadataPointer;
this.mirror = runtime().compilerToVm.getJavaMirror(this);
assert metadataPointer != 0;
assert getName().charAt(0) != '[' || isArray() : getName();
this.metadataPointer = metadataPointer;
// The mirror object must be in the global scope since
// this object will be cached in HotSpotJVMCIRuntime.resolvedJavaTypes
// and live across more than one compilation.
try (HotSpotObjectConstantScope global = HotSpotObjectConstantScope.enterGlobalScope()) {
this.mirror = runtime().compilerToVm.getJavaMirror(this);
assert getName().charAt(0) != '[' || isArray() : getName();
}
}
/**
@ -146,18 +152,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
}
@Override
public HotSpotResolvedObjectType getArrayClass() {
if (arrayOfType == null) {
try {
arrayOfType = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + getName(), this, true);
} catch (ClassNotFoundException e) {
throw new JVMCIError(e);
}
}
return arrayOfType;
}
@Override
public ResolvedJavaType getComponentType() {
return runtime().compilerToVm.getComponentType(this);
@ -580,6 +574,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
return null;
}
if (resolvedMethod.canBeStaticallyBound()) {
// No assumptions are required.
return new AssumptionResult<>(resolvedMethod);
}
ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
if (result != null) {
return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));

View File

@ -46,7 +46,6 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
@NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
private JavaKind kind;
private HotSpotResolvedObjectType arrayClass;
HotSpotObjectConstantImpl mirror;
/**
@ -87,14 +86,7 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
if (kind == JavaKind.Void) {
return null;
}
if (arrayClass == null) {
try {
arrayClass = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + kind.getTypeChar(), null, true);
} catch (ClassNotFoundException e) {
throw new JVMCIError(e);
}
}
return arrayClass;
return super.getArrayClass();
}
@Override

View File

@ -24,17 +24,52 @@ package jdk.vm.ci.hotspot;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
import jdk.vm.ci.meta.JavaConstant;
/**
* Encapsulates a JNI reference to an object in the HotSpot heap.
*
* {@link IndirectHotSpotObjectConstantImpl} objects are only allocated in the shared library heap.
*
* @see HotSpotObjectConstantScope
*/
final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl {
/**
* An object handle in {@code JVMCI::_jvmci_handles}.
* An object handle in {@code JVMCI::_object_handles}.
*/
private long objectHandle;
/**
* Lazily computed hash code.
*/
final long objectHandle;
private int hashCode;
final IndirectHotSpotObjectConstantImpl base;
private static class Audit {
final Object scope;
final long handle;
final Throwable origin;
Audit(Object scope, long handle, Throwable origin) {
this.scope = scope;
this.handle = handle;
this.origin = origin;
}
}
/**
* Details useful to audit a scoped handle used after its creating scope closes. Set to an
* {@link Audit} object if {@link HotSpotJVMCIRuntime.Option#AuditHandles} is true otherwise to
* {@link HotSpotObjectConstantScope#localScopeDescription}.
*/
private Object rawAudit;
@SuppressWarnings("serial")
@VMEntryPoint
private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) {
super(compressed);
@ -42,7 +77,20 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl
this.objectHandle = objectHandle;
this.base = null;
if (!skipRegister) {
HandleCleaner.create(this, objectHandle);
HotSpotObjectConstantScope scope = HotSpotObjectConstantScope.CURRENT.get();
if (scope != null && !scope.isGlobal()) {
scope.add(this);
if (HotSpotJVMCIRuntime.Option.AuditHandles.getBoolean()) {
rawAudit = new Audit(scope.localScopeDescription, objectHandle, new Throwable() {
@Override
public String toString() {
return "Created " + objectHandle;
}
});
}
} else {
HandleCleaner.create(this, objectHandle);
}
}
}
@ -50,12 +98,59 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl
super(compressed);
// This is a variant of an original object that only varies in compress vs uncompressed.
// Instead of creating a new handle, reference that object and objectHandle.
this.objectHandle = base.objectHandle;
// There should only be on level of indirection to the base object.
this.objectHandle = base.getHandle();
// There should only be one level of indirection to the base object.
assert base.base == null || base.base.base == null;
this.base = base.base != null ? base.base : base;
}
long getHandle() {
checkHandle();
return objectHandle;
}
private void checkHandle() {
if (objectHandle == 0L) {
String message;
if (rawAudit instanceof Audit) {
Audit audit = (Audit) rawAudit;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
ps.println("Foreign object reference " + audit.handle + " created in scope '" + audit.scope + "' is no longer valid. Origin: {");
audit.origin.printStackTrace(ps);
ps.print('}');
ps.flush();
message = baos.toString();
} else {
message = "Foreign object reference created in scope '" + rawAudit + "' is no longer valid. " +
"Set property " + Option.AuditHandles.getPropertyName() + "=true to show origin of invalid foreign references.";
}
throw new NullPointerException(message);
}
}
boolean isValid() {
return objectHandle != 0L;
}
@Override
public HotSpotResolvedObjectType getType() {
checkHandle();
return super.getType();
}
/**
* Clears the foreign object reference.
*/
void clear(Object scopeDescription) {
checkHandle();
CompilerToVM.compilerToVM().deleteGlobalHandle(objectHandle);
if (rawAudit == null) {
rawAudit = scopeDescription;
}
objectHandle = 0L;
}
@Override
public JavaConstant compress() {
assert !compressed;
@ -70,6 +165,7 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl
@Override
public int getIdentityHashCode() {
checkHandle();
int hash = hashCode;
if (hash == 0) {
hash = runtime().compilerToVm.getIdentityHashCode(this);

View File

@ -114,7 +114,7 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
}
IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y;
return runtime().compilerToVm.equals(x, indirectX.objectHandle, y, indirectY.objectHandle);
return runtime().compilerToVm.equals(x, indirectX.getHandle(), y, indirectY.getHandle());
}
@Override
@ -288,6 +288,10 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
return "CompilerObject<" + direct.object.getClass().getName() + ">";
}
IndirectHotSpotObjectConstantImpl indirect = (IndirectHotSpotObjectConstantImpl) object;
if (!indirect.isValid()) {
return "Instance<null>";
}
return "Instance<" + object.getType().toJavaName() + ">";
}

View File

@ -86,6 +86,29 @@ public class MetaUtil {
}
}
/**
* Classes for lambdas can have {@code /} characters that are not package separators. These are
* distinguished by being followed by a character that is not a
* {@link Character#isJavaIdentifierStart(char)} (e.g.,
* "jdk.vm.ci.runtime.test.TypeUniverse$$Lambda$1/869601985").
*/
private static String replacePackageSeparatorsWithDot(String name) {
int length = name.length();
int i = 0;
StringBuilder buf = new StringBuilder(length);
while (i < length - 1) {
char ch = name.charAt(i);
if (ch == '/' && Character.isJavaIdentifierStart(name.charAt(i + 1))) {
buf.append('.');
} else {
buf.append(ch);
}
i++;
}
buf.append(name.charAt(length - 1));
return buf.toString();
}
/**
* Converts a type name in internal form to an external form.
*
@ -99,7 +122,7 @@ public class MetaUtil {
public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
switch (name.charAt(0)) {
case 'L': {
String result = name.substring(1, name.length() - 1).replace('/', '.');
String result = replacePackageSeparatorsWithDot(name.substring(1, name.length() - 1));
if (!qualified) {
final int lastDot = result.lastIndexOf('.');
if (lastDot != -1) {
@ -109,7 +132,7 @@ public class MetaUtil {
return result;
}
case '[':
return classForNameCompatible ? name.replace('/', '.') : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
return classForNameCompatible ? replacePackageSeparatorsWithDot(name) : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
default:
if (name.length() != 1) {
throw new IllegalArgumentException("Illegal internal name: " + name);

View File

@ -68,16 +68,22 @@ public class TestMetaAccessProvider extends TypeUniverse {
metaAccess.encodeDeoptActionAndReason(DEOPT_ACTION, DEOPT_REASON, DEBUG_IDS[3]).asInt()
};
private static boolean isUnsafeAnoymous(ResolvedJavaType type) {
return type.getHostClass() != null;
}
@Test
public void lookupJavaTypeTest() {
for (Class<?> c : classes) {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
assertNotNull(c.toString(), type);
assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
assertEquals(c.toString(), c.getName(), type.toClassName());
if (!type.isArray()) {
assertEquals(c.toString(), c.getName(), type.toJavaName());
if (!isUnsafeAnoymous(type)) {
assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
assertEquals(c.toString(), c.getName(), type.toClassName());
if (!type.isArray()) {
assertEquals(c.toString(), c.getName(), type.toJavaName());
}
}
}
}
@ -92,7 +98,9 @@ public class TestMetaAccessProvider extends TypeUniverse {
ResolvedJavaType[] result = metaAccess.lookupJavaTypes(classes.toArray(new Class<?>[classes.size()]));
int counter = 0;
for (Class<?> aClass : classes) {
assertEquals("Unexpected javaType: " + result[counter] + " while expecting of class: " + aClass, result[counter].toClassName(), aClass.getName());
if (!isUnsafeAnoymous(result[counter])) {
assertEquals("Unexpected javaType: " + result[counter] + " while expecting of class: " + aClass, result[counter].toClassName(), aClass.getName());
}
counter++;
}
}

View File

@ -161,7 +161,11 @@ public class TestResolvedJavaType extends TypeUniverse {
for (Class<?> c : classes) {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
ResolvedJavaType host = type.getHostClass();
assertNull(host);
if (!type.equals(predicateType)) {
assertNull(host);
} else {
assertNotNull(host);
}
}
class LocalClass {}

View File

@ -51,6 +51,7 @@ import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static java.lang.reflect.Modifier.isFinal;
@ -68,6 +69,7 @@ public class TypeUniverse {
public static final ConstantReflectionProvider constantReflection = JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection();
public static final Collection<Class<?>> classes = new HashSet<>();
public static final Set<ResolvedJavaType> javaTypes;
public static final ResolvedJavaType predicateType;
public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
private static List<ConstantValue> constants;
@ -116,6 +118,9 @@ public class TypeUniverse {
for (Class<?> c : initialClasses) {
addClass(c);
}
Predicate<String> predicate = s -> s.length() == 1;
addClass(predicate.getClass());
predicateType = metaAccess.lookupJavaType(predicate.getClass());
javaTypes = Collections.unmodifiableSet(classes.stream().map(c -> metaAccess.lookupJavaType(c)).collect(Collectors.toSet()));
}