8232904: Update JVMCI

Reviewed-by: dnsimon
This commit is contained in:
Vladimir Kozlov 2019-10-24 16:58:39 -07:00
parent cd4d0bc498
commit e15849a0f8
12 changed files with 232 additions and 22 deletions

View File

@ -2330,6 +2330,16 @@ C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm
return true;
C2V_END
C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm))
if (base_thread == NULL) {
// Called from unattached JVMCI shared library thread
return 0L;
}
JVMCITraceMark jtm("getCurrentJavaThread");
assert(base_thread->is_Java_thread(), "just checking");
return (jlong) p2i(base_thread);
C2V_END
C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon))
if (base_thread == NULL) {
// Called from unattached JVMCI shared library thread
@ -2743,6 +2753,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "deleteGlobalHandle", CC "(J)V", FN_PTR(deleteGlobalHandle)},
{CC "registerNativeMethods", CC "(" CLASS ")[J", FN_PTR(registerNativeMethods)},
{CC "isCurrentThreadAttached", CC "()Z", FN_PTR(isCurrentThreadAttached)},
{CC "getCurrentJavaThread", CC "()J", FN_PTR(getCurrentJavaThread)},
{CC "attachCurrentThread", CC "(Z)Z", FN_PTR(attachCurrentThread)},
{CC "detachCurrentThread", CC "()V", FN_PTR(detachCurrentThread)},
{CC "translate", CC "(" OBJECT ")J", FN_PTR(translate)},

View File

@ -180,6 +180,7 @@
nonstatic_field(JavaThread, _pending_transfer_to_interpreter, bool) \
nonstatic_field(JavaThread, _jvmci_counters, jlong*) \
nonstatic_field(JavaThread, _should_post_on_exceptions_flag, int) \
nonstatic_field(JavaThread, _jni_environment, JNIEnv) \
nonstatic_field(JavaThread, _reserved_stack_activation, address) \
\
static_field(java_lang_Class, _klass_offset, int) \
@ -538,6 +539,7 @@
declare_constant(FieldInfo::field_slots) \
\
declare_constant(InstanceKlass::linked) \
declare_constant(InstanceKlass::being_initialized) \
declare_constant(InstanceKlass::fully_initialized) \
declare_constant(InstanceKlass::_misc_is_unsafe_anonymous) \
\

View File

@ -966,6 +966,11 @@ final class CompilerToVM {
*/
native boolean isCurrentThreadAttached();
/**
* @see HotSpotJVMCIRuntime#getCurrentJavaThread()
*/
native long getCurrentJavaThread();
/**
* @see HotSpotJVMCIRuntime#attachCurrentThread
*/

View File

@ -998,6 +998,14 @@ assert factories != null : "sanity";
return compilerToVm.isCurrentThreadAttached();
}
/**
* Gets the address of the HotSpot {@code JavaThread} C++ object for the current thread. This
* will return {@code 0} if called from an unattached JVMCI shared library thread.
*/
public long getCurrentJavaThread() {
return compilerToVm.getCurrentJavaThread();
}
/**
* Ensures the current thread is attached to the peer runtime.
*

View File

@ -52,4 +52,13 @@ public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements
}
return arrayOfType;
}
/**
* Checks whether this type is currently being initialized. If a type is being initialized it
* implies that it was {@link #isLinked() linked} and that the static initializer is currently
* being run.
*
* @return {@code true} if this type is being initialized
*/
abstract boolean isBeingInitialized();
}

View File

@ -359,6 +359,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
}
@Override
public boolean isBeingInitialized() {
return isArray() ? false : getInitState() == config().instanceKlassStateBeingInitialized;
}
@Override
public boolean isLinked() {
return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
@ -379,7 +384,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
public void initialize() {
if (!isInitialized()) {
runtime().compilerToVm.ensureInitialized(this);
assert isInitialized();
assert isInitialized() || isBeingInitialized();
}
}
@ -578,11 +583,6 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
return new AssumptionResult<>(resolvedMethod);
}
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

@ -149,6 +149,11 @@ public final class HotSpotResolvedPrimitiveType extends HotSpotResolvedJavaType
return true;
}
@Override
public boolean isBeingInitialized() {
return false;
}
@Override
public boolean isLinked() {
return true;

View File

@ -29,7 +29,6 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
@ -37,8 +36,8 @@ import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding;
/**
* Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte
* array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the
* total length of data exceeds the length of a SHA-1 digest, then a SHA-1 digest of the data is
* produced instead.
* total length of data exceeds the length of a SHA-1 digest and a SHA-1 digest algorithm is
* available, then a SHA-1 digest of the data is produced instead.
*/
final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding {
@ -152,21 +151,33 @@ final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements
}
/**
* Prototype SHA1 digest that is cloned before use.
* Prototype SHA1 digest.
*/
private static final MessageDigest SHA1 = getSHA1();
private static final int SHA1_LENGTH = SHA1.getDigestLength();
private static final MessageDigest SHA1;
private static MessageDigest getSHA1() {
/**
* Cloning the prototype is quicker than calling {@link MessageDigest#getInstance(String)} every
* time.
*/
private static final boolean SHA1_IS_CLONEABLE;
private static final int SHA1_LENGTH;
static {
MessageDigest sha1 = null;
boolean sha1IsCloneable = false;
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1 = MessageDigest.getInstance("SHA-1");
sha1.clone();
return sha1;
} catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
sha1IsCloneable = true;
} catch (NoSuchAlgorithmException e) {
// Should never happen given that SHA-1 is mandated in a
// compliant Java platform implementation.
throw new JVMCIError("Expect a cloneable implementation of a SHA-1 message digest to be available", e);
// compliant Java platform implementation. However, be
// conservative and fall back to not using a digest.
} catch (CloneNotSupportedException e) {
}
SHA1 = sha1;
SHA1_IS_CLONEABLE = sha1IsCloneable;
SHA1_LENGTH = SHA1 == null ? 20 : SHA1.getDigestLength();
}
/**
@ -175,12 +186,12 @@ final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements
*/
byte[] getByteArray() {
if (result == null) {
if (count > SHA1_LENGTH) {
if (SHA1 != null && count > SHA1_LENGTH) {
try {
MessageDigest md = (MessageDigest) SHA1.clone();
MessageDigest md = SHA1_IS_CLONEABLE ? (MessageDigest) SHA1.clone() : MessageDigest.getInstance("SHA-1");
md.update(buf, 0, count);
result = md.digest();
} catch (CloneNotSupportedException e) {
} catch (CloneNotSupportedException | NoSuchAlgorithmException e) {
throw new InternalError(e);
}
} else {

View File

@ -107,6 +107,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
final int instanceKlassStateBeingInitialized = getConstant("InstanceKlass::being_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*>*");

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2014, 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;
/**
* A wrapper that holds a strong reference to a "master" speculation log that
* {@linkplain HotSpotSpeculationLog#managesFailedSpeculations() manages} the failed speculations
* list.
*/
public class SharedHotSpotSpeculationLog extends HotSpotSpeculationLog {
private final HotSpotSpeculationLog masterLog;
public SharedHotSpotSpeculationLog(HotSpotSpeculationLog masterLog) {
super(masterLog.getFailedSpeculationsAddress());
this.masterLog = masterLog;
}
@Override
public String toString() {
return masterLog.toString();
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.meta;
import java.util.Arrays;
import java.util.function.Supplier;
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
/**
* An implementation of {@link SpeculationReason} based on encoded values.
*/
public class EncodedSpeculationReason implements SpeculationReason {
final int groupId;
final String groupName;
final Object[] context;
private SpeculationLog.SpeculationReasonEncoding encoding;
public EncodedSpeculationReason(int groupId, String groupName, Object[] context) {
this.groupId = groupId;
this.groupName = groupName;
this.context = context;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof EncodedSpeculationReason) {
if (obj instanceof EncodedSpeculationReason) {
EncodedSpeculationReason that = (EncodedSpeculationReason) obj;
return this.groupId == that.groupId && Arrays.equals(this.context, that.context);
}
return false;
}
return false;
}
@Override
public SpeculationLog.SpeculationReasonEncoding encode(Supplier<SpeculationLog.SpeculationReasonEncoding> encodingSupplier) {
if (encoding == null) {
encoding = encodingSupplier.get();
encoding.addInt(groupId);
for (Object o : context) {
if (o == null) {
encoding.addInt(0);
} else {
addNonNullObject(encoding, o);
}
}
}
return encoding;
}
static void addNonNullObject(SpeculationLog.SpeculationReasonEncoding encoding, Object o) {
Class<? extends Object> c = o.getClass();
if (c == String.class) {
encoding.addString((String) o);
} else if (c == Byte.class) {
encoding.addByte((Byte) o);
} else if (c == Short.class) {
encoding.addShort((Short) o);
} else if (c == Character.class) {
encoding.addShort((Character) o);
} else if (c == Integer.class) {
encoding.addInt((Integer) o);
} else if (c == Long.class) {
encoding.addLong((Long) o);
} else if (c == Float.class) {
encoding.addInt(Float.floatToRawIntBits((Float) o));
} else if (c == Double.class) {
encoding.addLong(Double.doubleToRawLongBits((Double) o));
} else if (o instanceof Enum) {
encoding.addInt(((Enum<?>) o).ordinal());
} else if (o instanceof ResolvedJavaMethod) {
encoding.addMethod((ResolvedJavaMethod) o);
} else if (o instanceof ResolvedJavaType) {
encoding.addType((ResolvedJavaType) o);
} else if (o instanceof ResolvedJavaField) {
encoding.addField((ResolvedJavaField) o);
} else {
throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName());
}
}
@Override
public int hashCode() {
return groupId + Arrays.hashCode(this.context);
}
@Override
public String toString() {
return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context));
}
}

View File

@ -78,7 +78,8 @@ public class TestHotSpotSpeculationLog {
public synchronized void testFailedSpeculations() {
HotSpotSpeculationLog log = new HotSpotSpeculationLog();
DummyReason reason1 = new DummyReason("dummy1");
DummyReason reason2 = new DummyReason("dummy2");
String longName = new String(new char[2000]).replace('\0', 'X');
DummyReason reason2 = new DummyReason(longName);
Assert.assertTrue(log.maySpeculate(reason1));
Assert.assertTrue(log.maySpeculate(reason2));