8225810: Update JVMCI
Reviewed-by: never, dnsimon
This commit is contained in:
parent
c956e7ca8d
commit
3b0ee5a6d8
@ -568,6 +568,33 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jcla
|
|||||||
return JVMCIENV->get_jobject(result);
|
return JVMCIENV->get_jobject(result);
|
||||||
C2V_END
|
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))
|
C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
|
||||||
requireInHotSpot("lookupClass", JVMCI_CHECK_NULL);
|
requireInHotSpot("lookupClass", JVMCI_CHECK_NULL);
|
||||||
if (mirror == 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);
|
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 CC (char*) /*cast a literal from (const char*)*/
|
||||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
|
#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 "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
|
||||||
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
|
{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 "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 "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)},
|
||||||
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},
|
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},
|
||||||
{CC "lookupNameAndTypeRefIndexInPool", CC "(" HS_CONSTANT_POOL "I)I", FN_PTR(lookupNameAndTypeRefIndexInPool)},
|
{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 "getFailedSpeculationsAddress", CC "(" HS_RESOLVED_METHOD ")J", FN_PTR(getFailedSpeculationsAddress)},
|
||||||
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},
|
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},
|
||||||
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
|
{CC "addFailedSpeculation", CC "(J[B)Z", FN_PTR(addFailedSpeculation)},
|
||||||
|
{CC "callSystemExit", CC "(I)V", FN_PTR(callSystemExit)},
|
||||||
};
|
};
|
||||||
|
|
||||||
int CompilerToVM::methods_count() {
|
int CompilerToVM::methods_count() {
|
||||||
|
@ -1361,6 +1361,9 @@ Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
|
|||||||
return Handle(THREAD, obj);
|
return Handle(THREAD, obj);
|
||||||
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
|
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
|
||||||
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(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);
|
oop result = resolve_handle(object_handle);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
|
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
|
||||||
|
@ -770,6 +770,12 @@ final class CompilerToVM {
|
|||||||
*/
|
*/
|
||||||
native HotSpotResolvedJavaType getComponentType(HotSpotResolvedObjectTypeImpl type);
|
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}.
|
* Forces initialization of {@code type}.
|
||||||
*/
|
*/
|
||||||
@ -978,4 +984,9 @@ final class CompilerToVM {
|
|||||||
* @see HotSpotJVMCIRuntime#detachCurrentThread()
|
* @see HotSpotJVMCIRuntime#detachCurrentThread()
|
||||||
*/
|
*/
|
||||||
native void detachCurrentThread();
|
native void detachCurrentThread();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HotSpotJVMCIRuntime#exitHotSpot(int)
|
||||||
|
*/
|
||||||
|
native void callSystemExit(int status);
|
||||||
}
|
}
|
||||||
|
@ -87,4 +87,9 @@ public class HotSpotCompilationRequest extends CompilationRequest {
|
|||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return id + ":" + super.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +223,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||||||
// so that -XX:+JVMCIPrintProperties shows the option.
|
// so that -XX:+JVMCIPrintProperties shows the option.
|
||||||
InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
|
InitTimer(Boolean.class, false, "Specifies if initialization timing is enabled."),
|
||||||
PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
|
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,
|
TraceMethodDataFilter(String.class, null,
|
||||||
"Enables tracing of profiling info when read by JVMCI.",
|
"Enables tracing of profiling info when read by JVMCI.",
|
||||||
"Empty value: trace all methods",
|
"Empty value: trace all methods",
|
||||||
@ -687,9 +689,11 @@ assert factories != null : "sanity";
|
|||||||
return Collections.unmodifiableMap(backends);
|
return Collections.unmodifiableMap(backends);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("try")
|
||||||
@VMEntryPoint
|
@VMEntryPoint
|
||||||
private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long compileState, int id) {
|
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";
|
assert result != null : "compileMethod must always return something";
|
||||||
HotSpotCompilationRequestResult hsResult;
|
HotSpotCompilationRequestResult hsResult;
|
||||||
if (result instanceof HotSpotCompilationRequestResult) {
|
if (result instanceof HotSpotCompilationRequestResult) {
|
||||||
@ -704,7 +708,6 @@ assert factories != null : "sanity";
|
|||||||
hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
|
hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hsResult;
|
return hsResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,4 +1035,14 @@ assert factories != null : "sanity";
|
|||||||
public void excludeFromJVMCICompilation(Module...modules) {
|
public void excludeFromJVMCICompilation(Module...modules) {
|
||||||
this.excludeFromJVMCICompilation = modules.clone();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -22,11 +22,15 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot;
|
package jdk.vm.ci.hotspot;
|
||||||
|
|
||||||
|
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.JavaConstant;
|
import jdk.vm.ci.meta.JavaConstant;
|
||||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||||
|
|
||||||
public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
|
public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
|
||||||
|
|
||||||
|
HotSpotResolvedObjectTypeImpl arrayOfType;
|
||||||
|
|
||||||
HotSpotResolvedJavaType(String name) {
|
HotSpotResolvedJavaType(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
@ -40,4 +44,12 @@ public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract JavaConstant getJavaMirror();
|
abstract JavaConstant getJavaMirror();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HotSpotResolvedObjectType getArrayClass() {
|
||||||
|
if (arrayOfType == null) {
|
||||||
|
arrayOfType = runtime().compilerToVm.getArrayType(this);
|
||||||
|
}
|
||||||
|
return arrayOfType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
private volatile HotSpotResolvedJavaField[] instanceFields;
|
private volatile HotSpotResolvedJavaField[] instanceFields;
|
||||||
private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
|
private volatile HotSpotResolvedObjectTypeImpl[] interfaces;
|
||||||
private HotSpotConstantPool constantPool;
|
private HotSpotConstantPool constantPool;
|
||||||
private HotSpotResolvedObjectType arrayOfType;
|
|
||||||
private final JavaConstant mirror;
|
private final JavaConstant mirror;
|
||||||
private HotSpotResolvedObjectTypeImpl superClass;
|
private HotSpotResolvedObjectTypeImpl superClass;
|
||||||
|
|
||||||
@ -103,18 +102,25 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
* Creates the JVMCI mirror for a {@link Class} object.
|
* 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
|
* <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>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param metadataPointer the Klass* to create the mirror for
|
* @param metadataPointer the Klass* to create the mirror for
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("try")
|
||||||
HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
|
HotSpotResolvedObjectTypeImpl(long metadataPointer, String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.metadataPointer = metadataPointer;
|
|
||||||
this.mirror = runtime().compilerToVm.getJavaMirror(this);
|
|
||||||
assert metadataPointer != 0;
|
assert metadataPointer != 0;
|
||||||
|
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();
|
assert getName().charAt(0) != '[' || isArray() : getName();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the metaspace Klass for this type.
|
* Gets the metaspace Klass for this type.
|
||||||
@ -146,18 +152,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
|
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
|
@Override
|
||||||
public ResolvedJavaType getComponentType() {
|
public ResolvedJavaType getComponentType() {
|
||||||
return runtime().compilerToVm.getComponentType(this);
|
return runtime().compilerToVm.getComponentType(this);
|
||||||
@ -580,6 +574,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resolvedMethod.canBeStaticallyBound()) {
|
||||||
|
// No assumptions are required.
|
||||||
|
return new AssumptionResult<>(resolvedMethod);
|
||||||
|
}
|
||||||
|
|
||||||
ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
|
ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
|
return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
|
||||||
|
@ -46,7 +46,6 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
|
|||||||
@NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
|
@NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
|
||||||
|
|
||||||
private JavaKind kind;
|
private JavaKind kind;
|
||||||
private HotSpotResolvedObjectType arrayClass;
|
|
||||||
HotSpotObjectConstantImpl mirror;
|
HotSpotObjectConstantImpl mirror;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,14 +86,7 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
|
|||||||
if (kind == JavaKind.Void) {
|
if (kind == JavaKind.Void) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (arrayClass == null) {
|
return super.getArrayClass();
|
||||||
try {
|
|
||||||
arrayClass = (HotSpotResolvedObjectType) runtime().compilerToVm.lookupType("[" + kind.getTypeChar(), null, true);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new JVMCIError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arrayClass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,17 +24,52 @@ package jdk.vm.ci.hotspot;
|
|||||||
|
|
||||||
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
|
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;
|
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 {
|
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;
|
private int hashCode;
|
||||||
|
|
||||||
final IndirectHotSpotObjectConstantImpl base;
|
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
|
@VMEntryPoint
|
||||||
private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) {
|
private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) {
|
||||||
super(compressed);
|
super(compressed);
|
||||||
@ -42,20 +77,80 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl
|
|||||||
this.objectHandle = objectHandle;
|
this.objectHandle = objectHandle;
|
||||||
this.base = null;
|
this.base = null;
|
||||||
if (!skipRegister) {
|
if (!skipRegister) {
|
||||||
|
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);
|
HandleCleaner.create(this, objectHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private IndirectHotSpotObjectConstantImpl(IndirectHotSpotObjectConstantImpl base, boolean compressed) {
|
private IndirectHotSpotObjectConstantImpl(IndirectHotSpotObjectConstantImpl base, boolean compressed) {
|
||||||
super(compressed);
|
super(compressed);
|
||||||
// This is a variant of an original object that only varies in compress vs uncompressed.
|
// 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.
|
// Instead of creating a new handle, reference that object and objectHandle.
|
||||||
this.objectHandle = base.objectHandle;
|
this.objectHandle = base.getHandle();
|
||||||
// There should only be on level of indirection to the base object.
|
// There should only be one level of indirection to the base object.
|
||||||
assert base.base == null || base.base.base == null;
|
assert base.base == null || base.base.base == null;
|
||||||
this.base = base.base != null ? base.base : base;
|
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
|
@Override
|
||||||
public JavaConstant compress() {
|
public JavaConstant compress() {
|
||||||
assert !compressed;
|
assert !compressed;
|
||||||
@ -70,6 +165,7 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIdentityHashCode() {
|
public int getIdentityHashCode() {
|
||||||
|
checkHandle();
|
||||||
int hash = hashCode;
|
int hash = hashCode;
|
||||||
if (hash == 0) {
|
if (hash == 0) {
|
||||||
hash = runtime().compilerToVm.getIdentityHashCode(this);
|
hash = runtime().compilerToVm.getIdentityHashCode(this);
|
||||||
|
@ -114,7 +114,7 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
|
|||||||
}
|
}
|
||||||
IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
|
IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x;
|
||||||
IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y;
|
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
|
@Override
|
||||||
@ -288,6 +288,10 @@ class SharedLibraryJVMCIReflection extends HotSpotJVMCIReflection {
|
|||||||
DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
|
DirectHotSpotObjectConstantImpl direct = (DirectHotSpotObjectConstantImpl) object;
|
||||||
return "CompilerObject<" + direct.object.getClass().getName() + ">";
|
return "CompilerObject<" + direct.object.getClass().getName() + ">";
|
||||||
}
|
}
|
||||||
|
IndirectHotSpotObjectConstantImpl indirect = (IndirectHotSpotObjectConstantImpl) object;
|
||||||
|
if (!indirect.isValid()) {
|
||||||
|
return "Instance<null>";
|
||||||
|
}
|
||||||
return "Instance<" + object.getType().toJavaName() + ">";
|
return "Instance<" + object.getType().toJavaName() + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
* 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) {
|
public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) {
|
||||||
switch (name.charAt(0)) {
|
switch (name.charAt(0)) {
|
||||||
case 'L': {
|
case 'L': {
|
||||||
String result = name.substring(1, name.length() - 1).replace('/', '.');
|
String result = replacePackageSeparatorsWithDot(name.substring(1, name.length() - 1));
|
||||||
if (!qualified) {
|
if (!qualified) {
|
||||||
final int lastDot = result.lastIndexOf('.');
|
final int lastDot = result.lastIndexOf('.');
|
||||||
if (lastDot != -1) {
|
if (lastDot != -1) {
|
||||||
@ -109,7 +132,7 @@ public class MetaUtil {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
return classForNameCompatible ? name.replace('/', '.') : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
|
return classForNameCompatible ? replacePackageSeparatorsWithDot(name) : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]";
|
||||||
default:
|
default:
|
||||||
if (name.length() != 1) {
|
if (name.length() != 1) {
|
||||||
throw new IllegalArgumentException("Illegal internal name: " + name);
|
throw new IllegalArgumentException("Illegal internal name: " + name);
|
||||||
|
@ -68,11 +68,16 @@ public class TestMetaAccessProvider extends TypeUniverse {
|
|||||||
metaAccess.encodeDeoptActionAndReason(DEOPT_ACTION, DEOPT_REASON, DEBUG_IDS[3]).asInt()
|
metaAccess.encodeDeoptActionAndReason(DEOPT_ACTION, DEOPT_REASON, DEBUG_IDS[3]).asInt()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static boolean isUnsafeAnoymous(ResolvedJavaType type) {
|
||||||
|
return type.getHostClass() != null;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void lookupJavaTypeTest() {
|
public void lookupJavaTypeTest() {
|
||||||
for (Class<?> c : classes) {
|
for (Class<?> c : classes) {
|
||||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||||
assertNotNull(c.toString(), type);
|
assertNotNull(c.toString(), type);
|
||||||
|
if (!isUnsafeAnoymous(type)) {
|
||||||
assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
|
assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
|
||||||
assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
|
assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
|
||||||
assertEquals(c.toString(), c.getName(), type.toClassName());
|
assertEquals(c.toString(), c.getName(), type.toClassName());
|
||||||
@ -81,6 +86,7 @@ public class TestMetaAccessProvider extends TypeUniverse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void lookupJavaTypeNegativeTest() {
|
public void lookupJavaTypeNegativeTest() {
|
||||||
@ -92,7 +98,9 @@ public class TestMetaAccessProvider extends TypeUniverse {
|
|||||||
ResolvedJavaType[] result = metaAccess.lookupJavaTypes(classes.toArray(new Class<?>[classes.size()]));
|
ResolvedJavaType[] result = metaAccess.lookupJavaTypes(classes.toArray(new Class<?>[classes.size()]));
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (Class<?> aClass : classes) {
|
for (Class<?> aClass : classes) {
|
||||||
|
if (!isUnsafeAnoymous(result[counter])) {
|
||||||
assertEquals("Unexpected javaType: " + result[counter] + " while expecting of class: " + aClass, result[counter].toClassName(), aClass.getName());
|
assertEquals("Unexpected javaType: " + result[counter] + " while expecting of class: " + aClass, result[counter].toClassName(), aClass.getName());
|
||||||
|
}
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,11 @@ public class TestResolvedJavaType extends TypeUniverse {
|
|||||||
for (Class<?> c : classes) {
|
for (Class<?> c : classes) {
|
||||||
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
ResolvedJavaType type = metaAccess.lookupJavaType(c);
|
||||||
ResolvedJavaType host = type.getHostClass();
|
ResolvedJavaType host = type.getHostClass();
|
||||||
|
if (!type.equals(predicateType)) {
|
||||||
assertNull(host);
|
assertNull(host);
|
||||||
|
} else {
|
||||||
|
assertNotNull(host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalClass {}
|
class LocalClass {}
|
||||||
|
@ -51,6 +51,7 @@ import java.util.Map;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static java.lang.reflect.Modifier.isFinal;
|
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 ConstantReflectionProvider constantReflection = JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection();
|
||||||
public static final Collection<Class<?>> classes = new HashSet<>();
|
public static final Collection<Class<?>> classes = new HashSet<>();
|
||||||
public static final Set<ResolvedJavaType> javaTypes;
|
public static final Set<ResolvedJavaType> javaTypes;
|
||||||
|
public static final ResolvedJavaType predicateType;
|
||||||
public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
|
public static final Map<Class<?>, Class<?>> arrayClasses = new HashMap<>();
|
||||||
|
|
||||||
private static List<ConstantValue> constants;
|
private static List<ConstantValue> constants;
|
||||||
@ -116,6 +118,9 @@ public class TypeUniverse {
|
|||||||
for (Class<?> c : initialClasses) {
|
for (Class<?> c : initialClasses) {
|
||||||
addClass(c);
|
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()));
|
javaTypes = Collections.unmodifiableSet(classes.stream().map(c -> metaAccess.lookupJavaType(c)).collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user