--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Fri Jun 21 13:04:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Fri Jun 21 16:21:13 2019 -0700
@@ -568,6 +568,33 @@
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 @@
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 @@
{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 @@
{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() {
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Fri Jun 21 13:04:14 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Fri Jun 21 16:21:13 2019 -0700
@@ -1361,6 +1361,9 @@
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());
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Fri Jun 21 16:21:13 2019 -0700
@@ -771,6 +771,12 @@
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}.
*/
native void ensureInitialized(HotSpotResolvedObjectTypeImpl type);
@@ -978,4 +984,9 @@
* @see HotSpotJVMCIRuntime#detachCurrentThread()
*/
native void detachCurrentThread();
+
+ /**
+ * @see HotSpotJVMCIRuntime#exitHotSpot(int)
+ */
+ native void callSystemExit(int status);
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java Fri Jun 21 16:21:13 2019 -0700
@@ -87,4 +87,9 @@
public int getId() {
return id;
}
+
+ @Override
+ public String toString() {
+ return id + ":" + super.toString();
+ }
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Fri Jun 21 16:21:13 2019 -0700
@@ -223,6 +223,8 @@
// 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 @@
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 @@
hsResult = HotSpotCompilationRequestResult.success(inlinedBytecodes);
}
}
-
return hsResult;
}
@@ -1032,4 +1035,14 @@
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);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantScope.java Fri Jun 21 16:21:13 2019 -0700
@@ -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);
+ }
+}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java Fri Jun 21 16:21:13 2019 -0700
@@ -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 @@
}
abstract JavaConstant getJavaMirror();
+
+ @Override
+ public HotSpotResolvedObjectType getArrayClass() {
+ if (arrayOfType == null) {
+ arrayOfType = runtime().compilerToVm.getArrayType(this);
+ }
+ return arrayOfType;
+ }
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Fri Jun 21 16:21:13 2019 -0700
@@ -72,7 +72,6 @@
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 @@
* 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);
+ assert metadataPointer != 0;
this.metadataPointer = metadataPointer;
- this.mirror = runtime().compilerToVm.getJavaMirror(this);
- assert metadataPointer != 0;
- assert getName().charAt(0) != '[' || isArray() : getName();
+
+ // 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();
+ }
}
/**
@@ -147,18 +153,6 @@
}
@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 @@
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));
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java Fri Jun 21 16:21:13 2019 -0700
@@ -46,7 +46,6 @@
@NativeImageReinitialize static HotSpotResolvedPrimitiveType[] primitives;
private JavaKind kind;
- private HotSpotResolvedObjectType arrayClass;
HotSpotObjectConstantImpl mirror;
/**
@@ -87,14 +86,7 @@
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
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java Fri Jun 21 16:21:13 2019 -0700
@@ -24,17 +24,52 @@
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}.
*/
- final long objectHandle;
+ private long objectHandle;
+
+ /**
+ * Lazily computed hash code.
+ */
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 @@
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 @@
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 @@
@Override
public int getIdentityHashCode() {
+ checkHandle();
int hash = hashCode;
if (hash == 0) {
hash = runtime().compilerToVm.getIdentityHashCode(this);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java Fri Jun 21 16:21:13 2019 -0700
@@ -114,7 +114,7 @@
}
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 @@
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() + ">";
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java Fri Jun 21 13:04:14 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java Fri Jun 21 16:21:13 2019 -0700
@@ -87,6 +87,29 @@
}
/**
+ * 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.
*
* @param name the internal name to convert
@@ -99,7 +122,7 @@
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 @@
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);
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java Fri Jun 21 13:04:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java Fri Jun 21 16:21:13 2019 -0700
@@ -68,16 +68,22 @@
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 @@
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++;
}
}
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Fri Jun 21 13:04:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Fri Jun 21 16:21:13 2019 -0700
@@ -161,7 +161,11 @@
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 {}
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java Fri Jun 21 13:04:14 2019 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java Fri Jun 21 16:21:13 2019 -0700
@@ -51,6 +51,7 @@
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 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 @@
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()));
}